From 9599e9888e441cd40ca4928baa3612046f152121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 15 Feb 2024 13:29:22 +0100 Subject: [PATCH 1/9] Limit release-please search depth & revert to auto version numbering ... --- release-please-config.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index a3cf9485..3575c54f 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,8 +1,9 @@ { - "last-release-sha": "4b6b9008737ff66321d5baf0a473fb698391a42b", - "release-as": "3.2.3", "release-type": "node", + "prerelease": false, "draft": true, + "release-search-depth": 10, + "commit-search-depth": 200, "changelog-sections": [ { "type": "feat", From 916d7c17090ae04dd3862f805ce80a0f79dd25a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 15 Feb 2024 13:29:50 +0100 Subject: [PATCH 2/9] Update docs wrt 3.2.3 --- README.md | 102 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 8245c2ec..e906cc78 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ Table of contents - [uninstall](#uninstall) - [uninstall-all](#uninstall-all) - [install](#install-1) - - [Older versions of Chrome](#older-versions-of-chrome) - - [Older versions of Firefox](#older-versions-of-firefox) + - [Older versions of Chrome](#older-versions-of-chrome) + - [Older versions of Firefox](#older-versions-of-firefox) - [list-available](#list-available) - [Hands-on examples](#hands-on-examples) - [QS Cloud, update a single app + apps in collection](#qs-cloud-update-a-single-app--apps-in-collection) @@ -502,6 +502,7 @@ If you need to set up a new virtual proxy the following configuration may be use ![Virtual proxy usuing Forms based authentitication, part 2](./docs/img/qseow-virtualproxy_2.png "Virtual proxy usuing Forms based authentitication, part 2") Finally, don't forget to use the `--prefix form` parameter when starting BSI. That option simply tells BSI to use a virtual proxy called "form" when connecting to the Sense server. + ### Using QSEoW's built-in Node.js It is possible, but in most cases not recommended to run Butler Sheet Icons as a Node.js app instead of using the stand-alone, pre-built Butler Sheet Icon binaries. @@ -597,18 +598,23 @@ Options: --logonuserid user ID for user to connect with when logging into web UI --logonpwd password for user to connect with --headless headless (=not visible) browser (true, false) (default: true) - --pagewait number of seconds to wait after moving to a new sheet. Set this high enough so the sheet has time to render properly (default: 5) + --pagewait number of seconds to wait after moving to a new sheet. Set this high enough so the sheet has time to render properly + (default: 5) --imagedir directory in which thumbnail images will be stored. Relative or absolute path (default: "./img") --contentlibrary Qlik Sense content library to which thumbnails will be uploaded (default: "Butler sheet thumbnails") - --includesheetpart which part of sheets should be used to take screenshots. 1=object area only, 2=1 + sheet title, 3=2 + selection bar, 4=3 + menu bar (default: "1") - --qliksensetag Used to control which Sense apps should have their sheets updated with new icons. All apps with this tag will be updated. (default: "") + --includesheetpart which part of sheets should be used to take screenshots. 1=object area only, 2=1 + sheet title, 3=2 + selection bar, 4=3 + + menu bar (default: "1") + --qliksensetag Used to control which Sense apps should have their sheets updated with new icons. All apps with this tag will be updated. + (default: "") --exclude-sheet-tag Sheets with this tag set will be excluded from sheet icon update. --exclude-sheet-number Sheet numbers (1=first sheet in an app) that will be excluded from sheet icon update. --exclude-sheet-title Use sheet titles to control which sheets that will be excluded from sheet icon update. - --sense-version Version of the QSEoW server to connect to (choices: "pre-2022-Nov", "2022-Nov", "2023-Feb", "2023-May", default: "2023-May") - --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. - (choices: "chrome", "firefox", default: "chrome") - --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. + --sense-version Version of the QSEoW server to connect to (choices: "pre-2022-Nov", "2022-Nov", "2023-Feb", "2023-May", "2023-Aug", + "2023-Nov", default: "2023-Nov") + --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers + are currently installed. (choices: "chrome", "firefox", default: "chrome") + --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. -h, --help display help for command ``` @@ -642,7 +648,8 @@ Options: --secure connection to Qlik Sense engine is via https (default: true) --apiuserdir user directory for user to connect with when using Sense APIs --apiuserid user ID for user to connect with when using Sense APIs - --qliksensetag Used to control which Sense apps should have their sheets updated with new icons. All apps with this tag will be updated. (default: "") + --qliksensetag Used to control which Sense apps should have their sheets updated with new icons. All apps with this tag will be updated. + (default: "") -h, --help display help for command ``` @@ -681,21 +688,25 @@ Multiple apps can be updated with a single command, using a Qlik Sense collectio Options: --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") --schemaversion Qlik Sense engine schema version (default: "12.612.0") - --tenanturl URL to Qlik Sense cloud tenant + --tenanturl URL or host of Qlik Sense cloud tenant. Example: "https://tenant.eu.qlikcloud.com" or "tenant.eu.qlikcloud.com" --apikey API key used to access the Sense APIs --logonuserid user ID for user to connect with when logging into web UI --logonpwd password for user to connect with --headless headless (=not visible) browser (true, false) (default: true) - --pagewait number of seconds to wait after moving to a new sheet. Set this high enough so the sheet has time to render properly (default: 5) + --pagewait number of seconds to wait after moving to a new sheet. Set this high enough so the sheet has time to render properly + (default: 5) --imagedir directory in which thumbnail images will be stored. Relative or absolute path (default: "./img") - --includesheetpart which part of sheets should be used to take screenshots. 1=object area only, 2=1 + sheet title, 3 not used, 4=full screen (default: "1") + --includesheetpart which part of sheets should be used to take screenshots. 1=object area only, 2=1 + sheet title, 3 not used, 4=full screen + (default: "1") --appid Qlik Sense app whose sheet icons should be modified. - --collectionid Used to control which Sense apps should have their sheets updated with new icons. All apps in this collection will be updated (default: "") + --collectionid Used to control which Sense apps should have their sheets updated with new icons. All apps in this collection will be + updated (default: "") --exclude-sheet-number Sheet numbers (1=first sheet in an app) that will be excluded from sheet icon update. --exclude-sheet-title Use sheet titles to control which sheets that will be excluded from sheet icon update. - --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. - (choices: "chrome", "firefox", default: "chrome") - --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. + --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers + are currently installed. (choices: "chrome", "firefox", default: "chrome") + --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. -h, --help display help for command ``` @@ -712,7 +723,7 @@ List available collections. Options: --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") - --tenanturl URL to Qlik Sense cloud tenant + --tenanturl URL or host of Qlik Sense cloud tenant. Example: "https://tenant.eu.qlikcloud.com" or "tenant.eu.qlikcloud.com" --apikey API key used to access the Sense APIs --outputformat Output format (choices: "table", "json", default: "table") -h, --help display help for command @@ -736,10 +747,11 @@ Remove all sheet icons from a Qlik Sense Cloud app. Options: --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") --schemaversion Qlik Sense engine schema version (default: "12.612.0") - --tenanturl URL to Qlik Sense cloud tenant + --tenanturl URL or host of Qlik Sense cloud tenant. Example: "https://tenant.eu.qlikcloud.com" or "tenant.eu.qlikcloud.com" --apikey API key used to access the Sense APIs --appid Qlik Sense app whose sheet icons should be modified. - --collectionid Used to control which Sense apps should have their sheets updated with new icons. All apps in this collection will be updated (default: "") + --collectionid Used to control which Sense apps should have their sheets updated with new icons. All apps in this collection will be updated + (default: "") -h, --help display help for command ``` @@ -818,10 +830,10 @@ Use the "butler-sheet-icons browser list-installed" command to see which browser Options: --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") - --browser Browser to uninstall (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are currently - installed. (default: "chrome") - --browser-version Version (=build id) of the browser to uninstall. Use "butler-sheet-icons browser list-installed" to see which browsers are currently - installed. + --browser Browser to uninstall (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. (default: "chrome") + --browser-version Version (=build id) of the browser to uninstall. Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. -h, --help display help for command ``` @@ -868,13 +880,14 @@ Use the "butler-sheet-icons browser list-installed" command to see which browser Options: --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") - --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. (choices: - "chrome", "firefox", default: "chrome") - --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed. + --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. (choices: "chrome", "firefox", default: "chrome") + --browser-version Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are + currently installed. -h, --help display help for command ``` -### Older versions of Chrome +#### Older versions of Chrome If using the command `browser list-available --browser chrome` you will see that there are several versions of Chrome available for download. If you then try to install an older version of Chrome it seems the Chrome team has removed the ability to download at least some older versions of Chrome. @@ -891,7 +904,7 @@ The output would look like this in PowerShell on Windows: There really isn't much to do about this, other than to use a newer version of Chrome. -### Older versions of Firefox +#### Older versions of Firefox Support for specific Firefox versions is pending, for now only the latest version of Firefox is supported. @@ -910,17 +923,21 @@ BSI will detect what operating system it's running on and only list browser vers There are not many options to this command, on Windows: ```powershell -.\butler-sheet-icons.exe browser list-installed --help +.\butler-sheet-icons.exe browser list-available --help ``` -```powershell -Usage: butler-sheet-icons browser list-installed [options] +```powershell +Usage: butler-sheet-icons browser list-available [options] -Show which browsers are currently installed and available for use by Butler Sheet Icons. +Show which browsers are available for download and installation by Butler Sheet Icons. Options: - --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") - -h, --help display help for command + --loglevel log level (choices: "error", "warn", "info", "verbose", "debug", "silly", default: "info") + --browser Browser to install (e.g. "chrome" or "firefox"). Use "butler-sheet-icons browser list-installed" to see which browsers are currently + installed. (choices: "chrome", "firefox", default: "chrome") + --channel Which of the browser's release channel versions should be listed? + This option is only used for Chrome. (choices: "stable", "beta", "dev", "canary", default: "stable") + -h, --help display help for command ``` # Hands-on examples @@ -941,7 +958,7 @@ Using PowerShell on Windows Server 2016, with the API key stored in an PowerShel Credentials and IDs removed intentionally, replace with ones relevant for your QS Cloud tenant/app. -`.\butler-sheet-icons.exe qscloud create-sheet-thumbnails --tenanturl .eu.qlikcloud.com --apikey "$BSI_CLOUD_APIKEY" --logonuserid "" --logonpwd --collectionid 6203d10 --headless true --includesheetpart 2 --appid 712cd6a1 --pagewait 10` +`.\butler-sheet-icons.exe qscloud create-sheet-thumbnails --tenanturl .eu.qlikcloud.com --apikey "$BSI_CLOUD_API_KEY" --logonuserid "" --logonpwd --collectionid 6203d10 --headless true --includesheetpart 2 --appid 712cd6a1 --pagewait 10` ![Create thumbnails in QS Cloud](./docs/img/qscloud-create-thumbnails-winssrv2016-ps-1.png "Create thumbnails in QS Cloud") @@ -957,7 +974,7 @@ Here we're showing the collections in a table, but it's also possible to get the Using bash on macOS: -` ./butler-sheet-icons qscloud list-collections --tenanturl $BSI_CLOUD_TENANTURL --apikey $BSI_CLOUD_APIKEY --outputformat table` +` ./butler-sheet-icons qscloud list-collections --tenanturl $BSI_CLOUD_TENANT_URL --apikey $BSI_CLOUD_API_KEY --outputformat table` ![List available collections in QS Cloud](./docs/img/qscloud-list-collection-macos-bash-1.png "List available collections in QS Cloud") @@ -1006,6 +1023,7 @@ Options: Commands: qseow qscloud + browser help [command] display help for command ➜ ``` @@ -1018,7 +1036,7 @@ Note: The command above assumes the certificates exported from QSEoW are availab ## QS Cloud, Docker container, update a single app + apps in collection -`docker run -it --rm ptarmiganlabs/butler-sheet-icons:latest qscloud create-sheet-thumbnails --tenanturl $BSI_CLOUD_TENANTURL --apikey $BSI_CLOUD_APIKEY --logonuserid $BSI_CLOUD_LOGONUSERID --logonpwd $BSI_CLOUD_LOGONPWD --collectionid $BSI_CLOUD_COLLECTIONID --headless true --includesheetpart 2 --appid $BSI_CLOUD_APPID --pagewait 10` +`docker run -it --rm ptarmiganlabs/butler-sheet-icons:latest qscloud create-sheet-thumbnails --tenanturl '$BSI_CLOUD_TENANT_URL' --apikey '$BSI_CLOUD_API_KEY' --logonuserid '$BSI_CLOUD_LOGON_USERID' --logonpwd '$BSI_CLOUD_LOGON_PWD' --collectionid '$BSI_CLOUD_COLLECTION_ID' --headless true --includesheetpart 2 --appid '$BSI_CLOUD_APP_ID' --pagewait 10` ![Run Butler Sheet Icons in Docker, updating Qlik Sense Cloud apps](./docs/img/qscloud-create-thumbnails-docker-1.png "Run Butler Sheet Icons in Docker, updating Qlik Sense Cloud apps") @@ -1032,11 +1050,11 @@ In other words: Butler Sheet Icons uses its own cache of browsers, it does not u On Windows this would be `butler-sheet-icons.exe browser list-installed`. ```powershell -PS C:\tools\butler-sheet-icons-win\demo-dir> .\butler-sheet-icons.exe browser list-installed +PS C:\tools\butler-sheet-icons-win> .\butler-sheet-icons.exe browser list-installed 2023-07-24T19:04:06.255Z info: Installed browsers: 2023-07-24T19:04:06.257Z info: chrome, build id=115.0.5790.102, platform=win64, path=C:\Users\goran\.cache\puppeteer\chrome\win64-115.0.5790.102 2023-07-24T19:04:06.266Z info: firefox, build id=117.0a1, platform=win64, path=C:\Users\goran\.cache\puppeteer\firefox\win64-117.0a1 -PS C:\tools\butler-sheet-icons-win\demo-dir> +PS C:\tools\butler-sheet-icons-win> ``` ## Install a browser into the BSI cache @@ -1048,11 +1066,11 @@ Use the `browser list-installed` command to see which browsers are currently ins Running the command without any options will install the latest stable version of Chrome into the cache: ```bash + + ➜ tools ./butler-sheet-icons browser install 2023-07-24T18:51:12.853Z info: Resolved browser build id: "115.0.5790.102" for browser "chrome" version "stable" 2023-07-24T18:51:12.854Z info: Installing browser... -(node:53339) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead. -(Use `butler-sheet-icons --trace-deprecation ...` to show where the warning was created) 2023-07-24T18:51:37.163Z info: Browser "chrome" version "115.0.5790.102" installed ➜ tools ``` From 0229d37365f97f06abbc6cf4527685e36c2c4c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 15 Feb 2024 13:30:27 +0100 Subject: [PATCH 3/9] .. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index e906cc78..efa18330 100644 --- a/README.md +++ b/README.md @@ -1083,9 +1083,6 @@ The same thing in PowerShell on Windows: PS C:\tools\butler-sheet-icons-win\demo-dir> .\butler-sheet-icons.exe browser install 2023-07-24T18:56:45.142Z info: Resolved browser build id: "115.0.5790.102" for browser "chrome" version "stable" 2023-07-24T18:56:45.143Z info: Installing browser... -(node:9540) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from( -) methods instead. -(Use `butler-sheet-icons --trace-deprecation ...` to show where the warning was created) 2023-07-24T18:57:00.221Z info: Browser "chrome" version "115.0.5790.102" installed PS C:\tools\butler-sheet-icons-win\demo-dir> ``` From e9fc470cfe1fb26f15fb21a4dfc71a1a51545b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 15 Feb 2024 21:18:08 +0100 Subject: [PATCH 4/9] feat(browser): In `list-available` command, show which versions can be used. Implements #496 --- src/butler-sheet-icons.js | 12 +++++---- src/lib/browser/browser-install.js | 22 +++++++++++++++- src/lib/browser/browser-list-available.js | 32 ++++++++++++++++++++--- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/butler-sheet-icons.js b/src/butler-sheet-icons.js index d6c452c3..c0c2da54 100644 --- a/src/butler-sheet-icons.js +++ b/src/butler-sheet-icons.js @@ -560,12 +560,12 @@ const program = new Command(); const res = await browserInstall(options, command); logger.debug(`Call to browserInstall succeeded: ${res}`); } catch (err) { - logger.error(`BROWSER MAIN 9: ${err}`); - if (err.message) { - logger.error(`BROWSER MAIN 9 (message): ${err.message}`); - } if (err.stack) { logger.error(`BROWSER MAIN 9 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`BROWSER MAIN 9 (message): ${err.message}`); + } else { + logger.error(`BROWSER MAIN 9: ${err}`); } } }) @@ -596,7 +596,9 @@ const program = new Command(); .action(async (options, command) => { try { const res = await browserListAvailable(options, command); - logger.debug(`Call to browserAvailable succeeded: ${res}`); + logger.debug( + `Call to browserAvailable succeeded: ${JSON.stringify(res, null, 2)}` + ); } catch (err) { logger.error(`BROWSER MAIN 10: ${err}`); if (err.message) { diff --git a/src/lib/browser/browser-install.js b/src/lib/browser/browser-install.js index 7adb3080..ae99dc7a 100644 --- a/src/lib/browser/browser-install.js +++ b/src/lib/browser/browser-install.js @@ -1,4 +1,9 @@ -const { install, resolveBuildId, detectBrowserPlatform } = require('@puppeteer/browsers'); +const { + install, + resolveBuildId, + detectBrowserPlatform, + canDownload, +} = require('@puppeteer/browsers'); const path = require('path'); const { homedir } = require('os'); @@ -42,6 +47,21 @@ const browserInstall = async (options, _command) => { logger.info( `Resolved browser build id: "${buildId}" for browser "${options.browser}" version "${options.browserVersion}"` ); + + // Ensure browser can be downloaded + const canDownloadBrowser = await canDownload({ + browser: options.browser, + buildId, + cacheDir: browserPath, + unpack: true, + }); + + if (!canDownloadBrowser) { + throw new Error( + `Browser "${options.browser}" version "${options.browserVersion}" cannot be downloaded. Please use the "list-available" command to check available versions` + ); + } + logger.info('Installing browser...'); const browser = await install({ diff --git a/src/lib/browser/browser-list-available.js b/src/lib/browser/browser-list-available.js index 5edbb929..689a53c1 100644 --- a/src/lib/browser/browser-list-available.js +++ b/src/lib/browser/browser-list-available.js @@ -1,4 +1,4 @@ -const { detectBrowserPlatform } = require('@puppeteer/browsers'); +const { detectBrowserPlatform, canDownload } = require('@puppeteer/browsers'); const path = require('path'); const { homedir } = require('os'); const axios = require('axios'); @@ -45,6 +45,8 @@ async function browserListAvailable(options) { // Get versions for the selected browser let browsersAvailable = []; if (options.browser === 'chrome') { + // https://developer.chrome.com/docs/web-platform/versionhistory/guide + // // Chome version history API: // https://developer.chrome.com/docs/versionhistory/guide/ // @@ -69,6 +71,10 @@ async function browserListAvailable(options) { // "nextPageToken": "" // } + logger.debug( + `Get Chrome versions from: https://versionhistory.googleapis.com/v1/chrome/platforms/${platform}/channels/${options.channel}/versions` + ); + const axiosConfig = { method: 'get', responseType: 'json', @@ -82,9 +88,27 @@ async function browserListAvailable(options) { // Output Chrome versions and names to info log if (browsersAvailable.length > 0) { logger.info(`Chrome versions from "${options.channel}" channel:`); - browsersAvailable.forEach((version) => { - logger.info(` ${version.version}, "${version.name}"`); - }); + logger.info( + 'Note that not all versions may be available for use with Butler Sheet Icons.' + ); + + // eslint-disable-next-line no-restricted-syntax + for (const version of browsersAvailable) { + // Can this version be downloaded? + // eslint-disable-next-line no-await-in-loop + const canDownloadBrowser = await canDownload({ + browser: options.browser, + buildId: version.version, + cacheDir: browserPath, + unpack: true, + }); + + if (canDownloadBrowser) { + logger.info(` ${version.version}, "${version.name}"`); + } else { + logger.info(` ${version.version}, "${version.name}" (not available)`); + } + } } else { logger.info('No Chrome versions available'); } From 3285b20759aeb7205d3c2ff1f55530177192a806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 15 Feb 2024 21:24:52 +0100 Subject: [PATCH 5/9] feat: Show app version on startup Implements #495 --- src/butler-sheet-icons.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/butler-sheet-icons.js b/src/butler-sheet-icons.js index c0c2da54..f7b17f00 100644 --- a/src/butler-sheet-icons.js +++ b/src/butler-sheet-icons.js @@ -33,6 +33,9 @@ const program = new Command(); 'Create thumbnail images based on the layout of each sheet in Qlik Sense Enterprise on Windows (QSEoW) applications.\nMultiple apps can be updated with a single command, using a Qlik Sense tag to identify which apps will be updated.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + logger.verbose(`appid=${options.appid}`); logger.verbose(`itemid=${options.itemid}`); try { @@ -187,6 +190,9 @@ const program = new Command(); .command('remove-sheet-icons') .description('Remove all sheet icons from a Qlik Sense Enterprise on Windows (QSEoW) app.') .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { const res = await qseowRemoveSheetIcons(options, command); logger.debug(`Call to qseowRemoveSheetIcons succeeded: ${res}`); @@ -264,6 +270,9 @@ const program = new Command(); 'Create thumbnail images based on the layout of each sheet in Qlik Sense Cloud applications.\nMultiple apps can be updated with a single command, using a Qlik Sense collection to identify which apps will be updated.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + logger.verbose(`appid=${options.appid}`); try { // Set default browser version per browser @@ -355,11 +364,15 @@ const program = new Command(); '--browser-version ', 'Version (=build id) of the browser to install. Use "butler-sheet-icons browser list-installed" to see which browsers are currently installed.' ); + // --------- cloud .command('list-collections') .description('List available collections.') .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + logger.verbose(`collection=${options.collection}`); try { const res = await qscloudListCollections(options, command); @@ -395,6 +408,9 @@ const program = new Command(); .command('remove-sheet-icons') .description('Remove all sheet icons from a Qlik Sense Cloud app.') .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { const res = await qscloudRemoveSheetIcons(options, command); logger.debug(`Call to qscloudRemoveSheetIcons succeeded: ${res}`); @@ -445,6 +461,9 @@ const program = new Command(); 'Show which browsers are currently installed and available for use by Butler Sheet Icons.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + logger.verbose(`appid=${options.appid}`); try { const res = await browserInstalled(options, command); @@ -472,6 +491,9 @@ const program = new Command(); 'Uninstall a browser from the Butler Sheet Icons cache.\nThis will remove the browser from the cache, but will not affect other browsers on this computer.\nUse the "butler-sheet-icons browser list-installed" command to see which browsers are currently installed.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { const res = await browserUninstall(options, command); logger.debug(`Call to browserUninstall succeeded: ${res}`); @@ -507,6 +529,9 @@ const program = new Command(); 'Uninstall all browsers from the Butler Sheet Icons cache.\nThis will remove all browsers from the cache, but will not affect other browsers on this computer.\nUse the "butler-sheet-icons browser list-installed" command to see which browsers are currently installed.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { const res = await browserUninstallAll(options, command); logger.debug(`Call to browserUninstallAll succeeded: ${res}`); @@ -533,6 +558,9 @@ const program = new Command(); 'Install a browser into the Butler Sheet Icons cache.\nThis will download the browser and install it into the cache, where it can be used by Butler Sheet Icons.\nUse the "butler-sheet-icons browser list-installed" command to see which browsers are currently installed.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { // Set default browser version per browser if (!options.browserVersion || options.browserVersion === '') { @@ -594,6 +622,9 @@ const program = new Command(); 'Show which browsers are available for download and installation by Butler Sheet Icons.' ) .action(async (options, command) => { + // Show app version + logger.info(`App version: ${appVersion}`); + try { const res = await browserListAvailable(options, command); logger.debug( From ba5299bd1fa207e6b5d2017755f7d1a680785a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 16 Feb 2024 08:42:35 +0100 Subject: [PATCH 6/9] Show unavailable browser versions only with verbose logging. See #496 --- src/lib/browser/browser-list-available.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/browser/browser-list-available.js b/src/lib/browser/browser-list-available.js index 689a53c1..90106181 100644 --- a/src/lib/browser/browser-list-available.js +++ b/src/lib/browser/browser-list-available.js @@ -88,7 +88,7 @@ async function browserListAvailable(options) { // Output Chrome versions and names to info log if (browsersAvailable.length > 0) { logger.info(`Chrome versions from "${options.channel}" channel:`); - logger.info( + logger.verbose( 'Note that not all versions may be available for use with Butler Sheet Icons.' ); @@ -106,7 +106,7 @@ async function browserListAvailable(options) { if (canDownloadBrowser) { logger.info(` ${version.version}, "${version.name}"`); } else { - logger.info(` ${version.version}, "${version.name}" (not available)`); + logger.verbose(` ${version.version}, "${version.name}" (not available)`); } } } else { From 61703c1c18bb8fcd70a23dade14c46c48e82aeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 16 Feb 2024 10:09:04 +0100 Subject: [PATCH 7/9] feat(cloud): Test connection to QS Cloud before starting BSI commands Implements #494 --- src/lib/cloud/cloud-collections.js | 58 ++++++++++++++++------- src/lib/cloud/cloud-create-thumbnails.js | 30 ++++++++++-- src/lib/cloud/cloud-remove-sheet-icons.js | 20 ++++++++ src/lib/cloud/cloud-repo-request.js | 28 ++++++----- src/lib/cloud/cloud-test-connection.js | 28 +++++++++++ 5 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 src/lib/cloud/cloud-test-connection.js diff --git a/src/lib/cloud/cloud-collections.js b/src/lib/cloud/cloud-collections.js index 1e7c231e..30b0b905 100644 --- a/src/lib/cloud/cloud-collections.js +++ b/src/lib/cloud/cloud-collections.js @@ -4,6 +4,7 @@ const { table } = require('table'); const { logger, setLoggingLevel, bsiExecutablePath, isPkg } = require('../../globals.js'); const QlikSaas = require('./cloud-repo'); +const { qscloudTestConnection } = require('./cloud-test-connection'); /** * @@ -30,13 +31,33 @@ const qscloudListCollections = async (options) => { try { saasInstance = new QlikSaas(cloudConfig); } catch (err) { - logger.error(`LIST COLLECTIONS 1: ${err}`); - if (err.message) { + if (err.stack) { + logger.error(`LIST COLLECTIONS 1 (stack): ${err.stack}`); + } else if (err.message) { logger.error(`LIST COLLECTIONS 1 (message): ${err.message}`); + } else { + logger.error(`LIST COLLECTIONS 1: ${err}`); } + + return false; + } + + // Test connection to QS Cloud by getting info about the user associated with the API key + try { + const res = await qscloudTestConnection(options, saasInstance); + logger.verbose( + `Connection to tenant ${options.tenanturl} successful: ${JSON.stringify(res)}` + ); + } catch (err) { if (err.stack) { logger.error(`LIST COLLECTIONS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`LIST COLLECTIONS 1 (message): ${err.message}`); + logger.error(`LIST COLLECTIONS 1 (error code): ${err.status}="${err.statusText}"`); + } else { + logger.error(`LIST COLLECTIONS 1: ${err}`); } + return false; } @@ -45,12 +66,12 @@ const qscloudListCollections = async (options) => { try { allCollections = await saasInstance.Get('collections'); } catch (err) { - logger.error(`LIST COLLECTIONS 2: ${err}`); - if (err.message) { - logger.error(`LIST COLLECTIONS 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`LIST COLLECTIONS 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`LIST COLLECTIONS 2 (message): ${err.message}`); + } else { + logger.error(`LIST COLLECTIONS 2: ${err}`); } return false; } @@ -98,13 +119,14 @@ const qscloudListCollections = async (options) => { return true; } catch (err) { - logger.error(`LIST COLLECTIONS 3: ${err}`); - if (err.message) { - logger.error(`LIST COLLECTIONS 3 (message): ${err.message}`); - } if (err.stack) { logger.error(`LIST COLLECTIONS 3 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`LIST COLLECTIONS 3 (message): ${err.message}`); + } else { + logger.error(`LIST COLLECTIONS 3: ${err}`); } + return false; } }; @@ -147,23 +169,23 @@ const qscloudVerifyCollectionExists = (options) => }) .catch((err) => { // Return error msg - logger.error(`CLOUD COLLECTION EXISTS 1: ${err}`); - if (err.message) { - logger.error(`CLOUD COLLECTION EXISTS 1 (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD COLLECTION EXISTS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD COLLECTION EXISTS 1 (message): ${err.message}`); + } else { + logger.error(`CLOUD COLLECTION EXISTS 1: ${err}`); } reject(new Error(`COLLECTION EXISTS 1: ${err}`)); }); } catch (err) { - logger.error(`CLOUD COLLECTION EXISTS 2: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`CLOUD COLLECTION EXISTS 2 (stack): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD COLLECTION EXISTS 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD COLLECTION EXISTS 2 (stack): ${err.message}`); + } else { + logger.error(`CLOUD COLLECTION EXISTS 2: ${JSON.stringify(err, null, 2)}`); } reject(new Error(`COLLECTION EXISTS: ${err}`)); diff --git a/src/lib/cloud/cloud-create-thumbnails.js b/src/lib/cloud/cloud-create-thumbnails.js index d09a5a1c..b5c3ea15 100644 --- a/src/lib/cloud/cloud-create-thumbnails.js +++ b/src/lib/cloud/cloud-create-thumbnails.js @@ -6,7 +6,7 @@ const puppeteer = require('puppeteer-core'); const fs = require('fs'); const path = require('path'); const { homedir } = require('os'); -const { install, computeExecutablePath } = require('@puppeteer/browsers'); +const { computeExecutablePath } = require('@puppeteer/browsers'); const { setupEnigmaConnection } = require('./cloud-enigma.js'); const { logger, setLoggingLevel, bsiExecutablePath, isPkg, sleep } = require('../../globals.js'); @@ -14,6 +14,7 @@ const { qscloudUploadToApp } = require('./cloud-upload.js'); const { qscloudUpdateSheetThumbnails } = require('./cloud-updatesheets.js'); const QlikSaas = require('./cloud-repo'); const { browserInstall } = require('../browser/browser-install.js'); +const { qscloudTestConnection } = require('./cloud-test-connection'); const selectorLoginPageUserName = '#lock-container > div > div > form > div > div > div:nth-child(3) > span > div > div > div > div > div > div > div > div > div > div.auth0-lock-input-block.auth0-lock-input-email > div.auth0-lock-input-wrap.auth0-lock-input-wrap-with-icon > input'; @@ -508,6 +509,25 @@ const qscloudCreateThumbnails = async (options) => { }; const saasInstance = new QlikSaas(cloudConfig); + // Test connection to QS Cloud by getting info about the user associated with the API key + try { + const res = await qscloudTestConnection(options, saasInstance); + logger.verbose( + `Connection to tenant ${options.tenanturl} successful: ${JSON.stringify(res)}` + ); + } catch (err) { + if (err.stack) { + logger.error(`LIST COLLECTIONS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`LIST COLLECTIONS 1 (message): ${err.message}`); + logger.error(`LIST COLLECTIONS 1 (error code): ${err.status}="${err.statusText}"`); + } else { + logger.error(`LIST COLLECTIONS 1: ${err}`); + } + + return false; + } + // Is there a specific app ID specified? if (options.appid) { appIdsToProcess.push(options.appid); @@ -582,12 +602,12 @@ const qscloudCreateThumbnails = async (options) => { return true; } catch (err) { - logger.error(`CLOUD CREATE THUMBNAILS 2: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`CLOUD CREATE THUMBNAILS 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD CREATE THUMBNAILS 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD CREATE THUMBNAILS 2 (message): ${err.message}`); + } else { + logger.error(`CLOUD CREATE THUMBNAILS 2: ${JSON.stringify(err, null, 2)}`); } return false; diff --git a/src/lib/cloud/cloud-remove-sheet-icons.js b/src/lib/cloud/cloud-remove-sheet-icons.js index 75989941..cbc6e53e 100644 --- a/src/lib/cloud/cloud-remove-sheet-icons.js +++ b/src/lib/cloud/cloud-remove-sheet-icons.js @@ -5,6 +5,7 @@ const enigma = require('enigma.js'); const { setupEnigmaConnection } = require('./cloud-enigma.js'); const { logger, setLoggingLevel, bsiExecutablePath, isPkg } = require('../../globals.js'); const QlikSaas = require('./cloud-repo'); +const { qscloudTestConnection } = require('./cloud-test-connection'); /** * @@ -170,6 +171,25 @@ const qscloudRemoveSheetIcons = async (options) => { }; const saasInstance = new QlikSaas(cloudConfig); + // Test connection to QS Cloud by getting info about the user associated with the API key + try { + const res = await qscloudTestConnection(options, saasInstance); + logger.verbose( + `Connection to tenant ${options.tenanturl} successful: ${JSON.stringify(res)}` + ); + } catch (err) { + if (err.stack) { + logger.error(`LIST COLLECTIONS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`LIST COLLECTIONS 1 (message): ${err.message}`); + logger.error(`LIST COLLECTIONS 1 (error code): ${err.status}="${err.statusText}"`); + } else { + logger.error(`LIST COLLECTIONS 1: ${err}`); + } + + return false; + } + // Is there a specific app ID specified? if (options.appid) { appIdsToProcess.push(options.appid); diff --git a/src/lib/cloud/cloud-repo-request.js b/src/lib/cloud/cloud-repo-request.js index cb3adac9..a3ae44dd 100644 --- a/src/lib/cloud/cloud-repo-request.js +++ b/src/lib/cloud/cloud-repo-request.js @@ -23,11 +23,22 @@ axios.interceptors.response.use( return response; }, (e) => { - throw Error({ + return Promise.reject({ status: e.response.status, statusText: e.response.statusText, message: e.message, }); + + // return { + // status: e.response.status, + // statusText: e.response.statusText, + // message: e.message, + // }; + // throw Error({ + // status: e.response.status, + // statusText: e.response.statusText, + // message: e.message, + // }); } ); @@ -65,17 +76,10 @@ async function makeRequest(config, data = []) { return makeRequest(config, returnData); } } catch (err) { - logger.error(`CLOUD Error in request to Qlik Cloud 1: ${err}`); - if (err.message) { - logger.error(`CLOUD Error in request to Qlik Cloud 1 (message): ${err.message}`); - } - if (err.stack) { - logger.error(`CLOUD Error in request to Qlik Cloud 1 (stack): ${err.stack}`); - } - - throw Error({ - message: 'Error in request to Qlik Cloud', - }); + return Promise.reject(err); + // throw Error({ + // message: 'Error in request to Qlik Cloud', + // }); } // Original code: diff --git a/src/lib/cloud/cloud-test-connection.js b/src/lib/cloud/cloud-test-connection.js new file mode 100644 index 00000000..9a6992a0 --- /dev/null +++ b/src/lib/cloud/cloud-test-connection.js @@ -0,0 +1,28 @@ +/* eslint-disable import/extensions */ +const { logger } = require('../../globals.js'); + +/** + * + * @param {*} saasInstance + * @returns + */ +const qscloudTestConnection = async (options, saasInstance) => { + // Test connection to QS Cloud by getting info about the user associated with the API key + try { + logger.info(`Testing connection to Qlik Sense Cloud...`); + const res = await saasInstance.Get('users/me'); + logger.info(`Connection to tenant ${options.tenanturl} successful.`); + logger.info(` Tenant ID : ${res?.tenantId}`); + logger.info(` User name : ${res?.name}`); + logger.info(` User email: ${res?.email}`); + logger.info(` User ID : ${res?.id}`); + logger.debug(`Full user info: ${JSON.stringify(res, null, 2)}`); + } catch (err) { + return Promise.reject(err); + } + return true; +}; + +module.exports = { + qscloudTestConnection, +}; From e971f6e491e37d1a73c87c61f44086c3958de9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 16 Feb 2024 12:05:27 +0100 Subject: [PATCH 8/9] refactor: Make error messages less spammy ... --- src/lib/cloud/cloud-create-thumbnails.js | 68 +++++++++--------- src/lib/cloud/cloud-remove-sheet-icons.js | 16 ++--- src/lib/cloud/cloud-repo-request.js | 22 ++---- src/lib/cloud/cloud-updatesheets.js | 8 +-- src/lib/cloud/cloud-upload.js | 8 +-- src/lib/qseow/qseow-certificates.js | 8 +-- src/lib/qseow/qseow-contentlibrary.js | 16 ++--- src/lib/qseow/qseow-create-thumbnails.js | 84 ++++++++++++----------- src/lib/qseow/qseow-remove-sheet-icons.js | 8 +-- src/lib/qseow/qseow-updatesheets.js | 8 +-- src/lib/qseow/qseow-upload.js | 16 ++--- 11 files changed, 125 insertions(+), 137 deletions(-) diff --git a/src/lib/cloud/cloud-create-thumbnails.js b/src/lib/cloud/cloud-create-thumbnails.js index b5c3ea15..76dbb739 100644 --- a/src/lib/cloud/cloud-create-thumbnails.js +++ b/src/lib/cloud/cloud-create-thumbnails.js @@ -35,12 +35,12 @@ const processCloudApp = async (appId, saasInstance, options) => { fs.mkdirSync(`${options.imagedir}/cloud/${appId}`, { recursive: true }); logger.verbose(`Created cloud image directory '${options.imagedir}/cloud/${appId}'`); } catch (err) { - logger.error(`CREATE THUMBNAILS 1: Error creating cloud image directory: ${err}`); - if (err.message) { - logger.error(`CREATE THUMBNAILS 1 (message): ${err.message}`); - } if (err.stack) { logger.error(`CREATE THUMBNAILS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CREATE THUMBNAILS 1 (message): ${err.message}`); + } else { + logger.error(`CREATE THUMBNAILS 1: Error creating cloud image directory: ${err}`); } throw Error('Error creating cloud image directory'); @@ -71,12 +71,12 @@ const processCloudApp = async (appId, saasInstance, options) => { ); existingThumbnails = await saasInstance.Get(`apps/${appId}/media/list/thumbnails`); } catch (err) { - logger.error(`CREATE THUMBNAILS 2: Error getting existing thumbnails: ${err}`); - if (err.message) { - logger.error(`CREATE THUMBNAILS 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`CREATE THUMBNAILS 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CREATE THUMBNAILS 2 (message): ${err.message}`); + } else { + logger.error(`CREATE THUMBNAILS 2: Error getting existing thumbnails: ${err}`); } throw Error('Error getting existing thumbnails'); @@ -98,14 +98,14 @@ const processCloudApp = async (appId, saasInstance, options) => { )}` ); } catch (err) { - logger.error( - `CREATE THUMBNAILS 3: Error deleting existing thumbnail: ${err}` - ); - if (err.message) { - logger.error(`CREATE THUMBNAILS 3 (message): ${err.message}`); - } if (err.stack) { logger.error(`CREATE THUMBNAILS 3 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CREATE THUMBNAILS 3 (message): ${err.message}`); + } else { + logger.error( + `CREATE THUMBNAILS 3: Error deleting existing thumbnail: ${err}` + ); } throw Error('Error deleting existing thumbnail'); @@ -230,16 +230,16 @@ const processCloudApp = async (appId, saasInstance, options) => { ], }); } catch (err) { - logger.error(`CLOUD APP: Could not launch virtual browser: ${err}. Exiting.`); - if (err.message) { - logger.error( - `CLOUD APP: Could not launch virtual browser (message): ${err.message}` - ); - } if (err.stack) { logger.error( `CLOUD APP: Could not launch virtual browser (stack): ${err.stack}` ); + } else if (err.message) { + logger.error( + `CLOUD APP: Could not launch virtual browser (message): ${err.message}` + ); + } else { + logger.error(`CLOUD APP: Could not launch virtual browser: ${err}. Exiting.`); } process.exit(1); @@ -427,16 +427,16 @@ const processCloudApp = async (appId, saasInstance, options) => { await browser.close(); logger.verbose('Closed virtual browser'); } catch (err) { - logger.error(`CLOUD APP: Could not close virtual browser: ${err}`); - if (err.message) { - logger.error( - `CLOUD APP: Could not close virtual browser (message): ${err.message}` - ); - } if (err.stack) { logger.error( `CLOUD APP: Could not close virtual browser (stack): ${err.stack}` ); + } else if (err.message) { + logger.error( + `CLOUD APP: Could not close virtual browser (message): ${err.message}` + ); + } else { + logger.error(`CLOUD APP: Could not close virtual browser: ${err}`); } } } @@ -459,12 +459,12 @@ const processCloudApp = async (appId, saasInstance, options) => { logger.info(`Done processing app ${appId}`); } catch (err) { - logger.error(`CLOUD APP: ${err.stack}`); - if (err.message) { - logger.error(`CLOUD APP (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD APP (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD APP (message): ${err.message}`); + } else { + logger.error(`CLOUD APP: ${err.stack}`); } } }; @@ -590,12 +590,12 @@ const qscloudCreateThumbnails = async (options) => { logger.verbose(`Done processing app ${appId}`); } catch (err) { - logger.error(`CLOUD PROCESS APP: ${err}`); - if (err.message) { - logger.error(`CLOUD PROCESS APP (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD PROCESS APP (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD PROCESS APP (message): ${err.message}`); + } else { + logger.error(`CLOUD PROCESS APP: ${err}`); } } } diff --git a/src/lib/cloud/cloud-remove-sheet-icons.js b/src/lib/cloud/cloud-remove-sheet-icons.js index cbc6e53e..67754393 100644 --- a/src/lib/cloud/cloud-remove-sheet-icons.js +++ b/src/lib/cloud/cloud-remove-sheet-icons.js @@ -136,12 +136,12 @@ const removeSheetIconsCloudApp = async (appId, saasInstance, options) => { logger.info(`Done processing app ${appId}`); } catch (err) { - logger.error(`CLOUD REMOVE SHEET ICONS 1: ${err}`); - if (err.message) { - logger.error(`CLOUD REMOVE SHEET ICONS 1 (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD REMOVE SHEET ICONS 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD REMOVE SHEET ICONS 1 (message): ${err.message}`); + } else { + logger.error(`CLOUD REMOVE SHEET ICONS 1: ${err}`); } } }; @@ -264,12 +264,12 @@ const qscloudRemoveSheetIcons = async (options) => { return true; } catch (err) { - logger.error(`CLOUD REMOVE THUMBNAILS 3: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`CLOUD REMOVE THUMBNAILS 3 (message): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD REMOVE THUMBNAILS 3 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD REMOVE THUMBNAILS 3 (message): ${err.message}`); + } else { + logger.error(`CLOUD REMOVE THUMBNAILS 3: ${JSON.stringify(err, null, 2)}`); } return false; diff --git a/src/lib/cloud/cloud-repo-request.js b/src/lib/cloud/cloud-repo-request.js index a3ae44dd..ae998ca8 100644 --- a/src/lib/cloud/cloud-repo-request.js +++ b/src/lib/cloud/cloud-repo-request.js @@ -22,24 +22,13 @@ axios.interceptors.response.use( return response; }, - (e) => { - return Promise.reject({ + (e) => + // eslint-disable-next-line prefer-promise-reject-errors + Promise.reject({ status: e.response.status, statusText: e.response.statusText, message: e.message, - }); - - // return { - // status: e.response.status, - // statusText: e.response.statusText, - // message: e.message, - // }; - // throw Error({ - // status: e.response.status, - // statusText: e.response.statusText, - // message: e.message, - // }); - } + }) ); function bufferToStream(buffer) { @@ -77,9 +66,6 @@ async function makeRequest(config, data = []) { } } catch (err) { return Promise.reject(err); - // throw Error({ - // message: 'Error in request to Qlik Cloud', - // }); } // Original code: diff --git a/src/lib/cloud/cloud-updatesheets.js b/src/lib/cloud/cloud-updatesheets.js index fb266bee..2f98c005 100644 --- a/src/lib/cloud/cloud-updatesheets.js +++ b/src/lib/cloud/cloud-updatesheets.js @@ -105,12 +105,12 @@ const qscloudUpdateSheetThumbnails = async (createdFiles, appId, options) => { logger.error(`Error closing session for QS Cloud app ${appId}`); } } catch (err) { - logger.error(`CLOUD UPDATE SHEETS: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`CLOUD UPDATE SHEETS (stack): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD UPDATE SHEETS (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD UPDATE SHEETS (stack): ${err.message}`); + } else { + logger.error(`CLOUD UPDATE SHEETS: ${JSON.stringify(err, null, 2)}`); } process.exit(1); diff --git a/src/lib/cloud/cloud-upload.js b/src/lib/cloud/cloud-upload.js index bfec7fee..3ae472d1 100644 --- a/src/lib/cloud/cloud-upload.js +++ b/src/lib/cloud/cloud-upload.js @@ -79,12 +79,12 @@ const qscloudUploadToApp = async (filesToUpload, appId, options) => { } } } catch (err) { - logger.error(`CLOUD UPLOAD 2: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`CLOUD UPLOAD 2 (stack): ${err.message}`); - } if (err.stack) { logger.error(`CLOUD UPLOAD 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`CLOUD UPLOAD 2 (stack): ${err.message}`); + } else { + logger.error(`CLOUD UPLOAD 2: ${JSON.stringify(err, null, 2)}`); } } }; diff --git a/src/lib/qseow/qseow-certificates.js b/src/lib/qseow/qseow-certificates.js index 25fffb9c..1f22ad68 100644 --- a/src/lib/qseow/qseow-certificates.js +++ b/src/lib/qseow/qseow-certificates.js @@ -57,12 +57,12 @@ const qseowVerifyCertificatesExist = (options) => resolve(true); } catch (err) { - logger.error(`QSEOW CERT CHECK: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`QSEOW CERT CHECK (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW CERT CHECK (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW CERT CHECK (message): ${err.message}`); + } else { + logger.error(`QSEOW CERT CHECK: ${JSON.stringify(err, null, 2)}`); } resolve(false); diff --git a/src/lib/qseow/qseow-contentlibrary.js b/src/lib/qseow/qseow-contentlibrary.js index f8e8488d..3919322f 100644 --- a/src/lib/qseow/qseow-contentlibrary.js +++ b/src/lib/qseow/qseow-contentlibrary.js @@ -37,23 +37,23 @@ const qseowVerifyContentLibraryExists = (options) => }) .catch((err) => { // Return error msg - logger.error(`QSEOW CONTENT LIBRARY 1: ${err}`); - if (err.message) { - logger.error(`QSEOW CONTENT LIBRARY 1 (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW CONTENT LIBRARY 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW CONTENT LIBRARY 1 (message): ${err.message}`); + } else { + logger.error(`QSEOW CONTENT LIBRARY 1: ${err}`); } reject(new Error(`CONTENT LIBRARY 1: ${err}`)); }); } catch (err) { - logger.error(`QSEOW CONTENT LIBRARY 2: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`QSEOW CONTENT LIBRARY 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW CONTENT LIBRARY 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW CONTENT LIBRARY 2 (message): ${err.message}`); + } else { + logger.error(`QSEOW CONTENT LIBRARY 2: ${JSON.stringify(err, null, 2)}`); } reject(new Error(`CONTENT LIBRARY 2: ${err}`)); diff --git a/src/lib/qseow/qseow-create-thumbnails.js b/src/lib/qseow/qseow-create-thumbnails.js index 499b26bf..398b9411 100644 --- a/src/lib/qseow/qseow-create-thumbnails.js +++ b/src/lib/qseow/qseow-create-thumbnails.js @@ -239,14 +239,14 @@ const processQSEoWApp = async (appId, g, options) => { ], }); } catch (err) { - logger.error(`QSEOW Could not launch virtual browser: ${err}. Exiting.`); - if (err.message) { + if (err.stack) { + logger.error(`QSEOW Could not launch virtual browser (stack): ${err.stack}`); + } else if (err.message) { logger.error( `QSEOW Could not launch virtual browser (message): ${err.message}` ); - } - if (err.stack) { - logger.error(`QSEOW Could not launch virtual browser (stack): ${err.stack}`); + } else { + logger.error(`QSEOW Could not launch virtual browser: ${err}. Exiting.`); } process.exit(1); @@ -477,15 +477,17 @@ const processQSEoWApp = async (appId, g, options) => { page.goto(hubUrl, { waitUntil: 'networkidle2', timeout: 90000 }), ]); } catch (err) { - logger.error(`QSEOW: Could not open hub after generating thumbnail images: ${err}`); - if (err.message) { + if (err.stack) { + logger.error( + `QSEOW: Could not open hub after generating thumbnail images (stack): ${err.stack}` + ); + } else if (err.message) { logger.error( `QSEOW: Could not open hub after generating thumbnail images (message): ${err.message}` ); - } - if (err.stack) { + } else { logger.error( - `QSEOW: Could not open hub after generating thumbnail images (stack): ${err.stack}` + `QSEOW: Could not open hub after generating thumbnail images: ${err}` ); } } @@ -502,17 +504,17 @@ const processQSEoWApp = async (appId, g, options) => { // Click user button and wait for page to load await Promise.all([elementHandle[0].click()]); } catch (err) { - logger.error( - `QSEOW: Error waiting for, or clicking, user button in hub default view: ${err}` - ); - if (err.message) { + if (err.stack) { + logger.error( + `QSEOW: Error waiting for, or clicking, user button in hub default view (stack): ${err.stack}` + ); + } else if (err.message) { logger.error( `QSEOW: Error waiting for, or clicking, user button in hub default view (message): ${err.message}` ); - } - if (err.stack) { + } else { logger.error( - `QSEOW: Error waiting for, or clicking, user button in hub default view (stack): ${err.stack}` + `QSEOW: Error waiting for, or clicking, user button in hub default view: ${err}` ); } } @@ -528,17 +530,17 @@ const processQSEoWApp = async (appId, g, options) => { await Promise.all([elementHandle[0].click()]); await sleep(options.pagewait * 1000); } catch (err) { - logger.error( - `QSEOW: Error while waiting for, or clicking, logout button in hub's user menu: ${err}` - ); - if (err.message) { + if (err.stack) { + logger.error( + `QSEOW: Error while waiting for, or clicking, logout button in hub's user menu (stack): ${err.stack}` + ); + } else if (err.message) { logger.error( `QSEOW: Error while waiting for, or clicking, logout button in hub's user menu (message): ${err.message}` ); - } - if (err.stack) { + } else { logger.error( - `QSEOW: Error while waiting for, or clicking, logout button in hub's user menu (stack): ${err.stack}` + `QSEOW: Error while waiting for, or clicking, logout button in hub's user menu: ${err}` ); } } @@ -547,14 +549,14 @@ const processQSEoWApp = async (appId, g, options) => { await browser.close(); logger.verbose('Closed virtual browser'); } catch (err) { - logger.error(`QSEOW: Could not close virtual browser: ${err}`); - if (err.message) { + if (err.stack) { + logger.error(`QSEOW: Could not close virtual browser (stack): ${err.stack}`); + } else if (err.message) { logger.error( `QSEOW: Could not close virtual browser (message): ${err.message}` ); - } - if (err.stack) { - logger.error(`QSEOW: Could not close virtual browser (stack): ${err.stack}`); + } else { + logger.error(`QSEOW: Could not close virtual browser: ${err}`); } } } @@ -575,12 +577,12 @@ const processQSEoWApp = async (appId, g, options) => { logger.info(`Done processing app ${appId}`); } catch (err) { - logger.error(`QSEOW: processQSEoWApp: ${err}`); - if (err.message) { - logger.error(`QSEOW: processQSEoWApp (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW: processQSEoWApp (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW: processQSEoWApp (message): ${err.message}`); + } else { + logger.error(`QSEOW: processQSEoWApp: ${err}`); } } }; @@ -684,24 +686,24 @@ const qseowCreateThumbnails = async (options) => { logger.verbose(`Done processing app ${appId}`); } catch (err) { - logger.error(`QSEOW PROCESS APP: ${err}`); - if (err.message) { - logger.error(`QSEOW PROCESS APP (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW PROCESS APP (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW PROCESS APP (message): ${err.message}`); + } else { + logger.error(`QSEOW PROCESS APP: ${err}`); } } } return true; } catch (err) { - logger.error(`QSEOW CREATE THUMBNAILS 2: ${err}`); - if (err.message) { - logger.error(`QSEOW CREATE THUMBNAILS 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW CREATE THUMBNAILS 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW CREATE THUMBNAILS 2 (message): ${err.message}`); + } else { + logger.error(`QSEOW CREATE THUMBNAILS 2: ${err}`); } return false; diff --git a/src/lib/qseow/qseow-remove-sheet-icons.js b/src/lib/qseow/qseow-remove-sheet-icons.js index fcd97477..db289f6c 100644 --- a/src/lib/qseow/qseow-remove-sheet-icons.js +++ b/src/lib/qseow/qseow-remove-sheet-icons.js @@ -108,12 +108,12 @@ const removeSheetIconsQSEoWApp = async (appId, g, options) => { logger.info(`Done processing app ${appId}`); } catch (err) { - logger.error(`QSEOW: removeSheetIconsQSEoWApp: ${err}`); - if (err.message) { - logger.error(`QSEOW: removeSheetIconsQSEoWApp (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW: removeSheetIconsQSEoWApp (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW: removeSheetIconsQSEoWApp (message): ${err.message}`); + } else { + logger.error(`QSEOW: removeSheetIconsQSEoWApp: ${err}`); } } }; diff --git a/src/lib/qseow/qseow-updatesheets.js b/src/lib/qseow/qseow-updatesheets.js index 16d5f34c..b68a8137 100644 --- a/src/lib/qseow/qseow-updatesheets.js +++ b/src/lib/qseow/qseow-updatesheets.js @@ -103,12 +103,12 @@ const qseowUpdateSheetThumbnails = async (createdFiles, appId, options) => { logger.error(`Error closing session for QSEoW app ${appId} on host ${options.host}`); } } catch (err) { - logger.error(`QSEOW UPDATE SHEETS: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`QSEOW UPDATE SHEETS (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW UPDATE SHEETS (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW UPDATE SHEETS (message): ${err.message}`); + } else { + logger.error(`QSEOW UPDATE SHEETS: ${JSON.stringify(err, null, 2)}`); } process.exit(1); diff --git a/src/lib/qseow/qseow-upload.js b/src/lib/qseow/qseow-upload.js index bd507549..ea09471f 100644 --- a/src/lib/qseow/qseow-upload.js +++ b/src/lib/qseow/qseow-upload.js @@ -66,12 +66,12 @@ const qseowUploadToContentLibrary = async (filesToUpload, appId, options) => { logger.debug(`QSEoW image upload result=${JSON.stringify(result)}`); logger.verbose(`QSEoW image upload done: ${JSON.stringify(file)}`); } catch (err) { - logger.error(`QSEOW UPLOAD 1: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`QSEOW UPLOAD 1 (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW UPLOAD 1 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW UPLOAD 1 (message): ${err.message}`); + } else { + logger.error(`QSEOW UPLOAD 1: ${JSON.stringify(err, null, 2)}`); } } } else if (fileStat.isDirectory()) { @@ -79,12 +79,12 @@ const qseowUploadToContentLibrary = async (filesToUpload, appId, options) => { } } } catch (err) { - logger.error(`QSEOW UPLOAD 2: ${JSON.stringify(err, null, 2)}`); - if (err.message) { - logger.error(`QSEOW UPLOAD 2 (message): ${err.message}`); - } if (err.stack) { logger.error(`QSEOW UPLOAD 2 (stack): ${err.stack}`); + } else if (err.message) { + logger.error(`QSEOW UPLOAD 2 (message): ${err.message}`); + } else { + logger.error(`QSEOW UPLOAD 2: ${JSON.stringify(err, null, 2)}`); } } }; From ed32a01aa161f2c49088e630571716de1d7bb8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 16 Feb 2024 12:53:52 +0100 Subject: [PATCH 9/9] Supress deprecated... messages from Node --- .github/workflows/ci.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4b137214..b1f6ae24 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,7 @@ jobs: build: | cd src ./node_modules/.bin/esbuild "${env:DIST_FILE_NAME}.js" --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${env:DIST_FILE_NAME}.exe" -t node18-win-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${env:DIST_FILE_NAME}.exe" -t node18-win-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip dir cd .. @@ -62,7 +62,7 @@ jobs: build: | cd src ./node_modules/.bin/esbuild ${DIST_FILE_NAME}.js --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${DIST_FILE_NAME}" -t node18-macos-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${DIST_FILE_NAME}" -t node18-macos-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip cd .. chmod +x "${DIST_FILE_NAME}" @@ -120,7 +120,7 @@ jobs: build: | cd src ./node_modules/.bin/esbuild ${DIST_FILE_NAME}.js --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${DIST_FILE_NAME}" -t node18-linux-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${DIST_FILE_NAME}" -t node18-linux-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip cd .. chmod +x ${DIST_FILE_NAME} @@ -586,7 +586,7 @@ jobs: pwd cd src ./node_modules/.bin/esbuild ${DIST_FILE_NAME}.js --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${DIST_FILE_NAME}" -t node18-macos-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${DIST_FILE_NAME}" -t node18-macos-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip cd .. chmod +x "${DIST_FILE_NAME}" @@ -713,7 +713,7 @@ jobs: run: | cd src ./node_modules/.bin/esbuild "${env:DIST_FILE_NAME}.js" --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${env:DIST_FILE_NAME}.exe" -t node18-win-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${env:DIST_FILE_NAME}.exe" -t node18-win-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip cd .. @@ -819,7 +819,7 @@ jobs: run: | cd src ./node_modules/.bin/esbuild ${DIST_FILE_NAME}.js --bundle --external:vm2 --external:axios --outfile=build.cjs --format=cjs --platform=node --target=node18.5.0 - pkg --output "../${DIST_FILE_NAME}" -t node18-linux-x64 ./build.cjs --config package.json --compress GZip + pkg --output "../${DIST_FILE_NAME}" -t node18-linux-x64 ./build.cjs --config package.json --options no-deprecation --compress GZip cd .. chmod +x ${DIST_FILE_NAME}