From 9115f2869b31a4703acc471bf9c27ffb8bf69fb1 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 6 Jul 2023 23:18:42 +0200 Subject: [PATCH 01/18] chore: remove prettier --- package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index ba71dba..5ba4206 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "main": "src/index.js", "type": "module", "scripts": { - "format": "prettier -w .", "lint": "eslint --ext .js --ignore-pattern dist --ignore-pattern pkg" }, "license": "MIT", @@ -19,6 +18,5 @@ }, "devDependencies": { "@companion-module/tools": "^1.3.2" - }, - "prettier": "@companion-module/tools/.prettierrc.json" + } } \ No newline at end of file From db65c751cdee5214736588901c712b57ad690f12 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 6 Jul 2023 23:22:43 +0200 Subject: [PATCH 02/18] chore: switch to stagetimer house style replace old eslint config with new flat config format, introduce .editorconfig --- .editorconfig | 5 +++++ .eslintrc.json | 12 ------------ eslint.config.js | 31 +++++++++++++++++++++++++++++++ package.json | 2 +- 4 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 .editorconfig delete mode 100644 .eslintrc.json create mode 100644 eslint.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..158e4f3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,json}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 09040d2..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es2021": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 12 - }, - "rules": {} -} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..1f6a0ce --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,31 @@ +import js from '@eslint/js' +import globals from 'globals' + +export default [ + js.configs.recommended, + { + languageOptions: { + globals: { + ...globals.nodeBuiltin, + }, + }, + }, + { + files: ['**/*.js'], + rules: { + 'indent': ['warn', 2, { 'SwitchCase': 1 }], + 'quotes': ['warn', 'single'], + 'semi': ['warn', 'never'], + 'comma-dangle': ['warn', 'always-multiline'], + 'no-console': 'warn', + 'no-unused-vars': ['warn', { 'args': 'all', 'argsIgnorePattern': '^_' }], + 'no-var': 'warn', + 'no-duplicate-imports': 'warn', + 'no-useless-return': 'warn', + 'space-before-function-paren': ['warn', 'always'], + 'object-curly-spacing': ['warn', 'always'], + 'no-use-before-define': ['error', 'nofunc'], + 'no-unused-expressions': 'error', + }, + }, +] diff --git a/package.json b/package.json index 5ba4206..d24fe7d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "main": "src/index.js", "type": "module", "scripts": { - "lint": "eslint --ext .js --ignore-pattern dist --ignore-pattern pkg" + "lint": "eslint ./src" }, "license": "MIT", "repository": { From b574394279403badb83e5beaf04a7483a2f0d1e4 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 6 Jul 2023 23:40:41 +0200 Subject: [PATCH 03/18] style: convert tabs to spaces --- companion/manifest.json | 68 ++-- jsconfig.json | 16 +- package.json | 42 +- src/actions.js | 540 ++++++++++++------------ src/api.js | 162 ++++---- src/assets.js | 58 +-- src/config.js | 100 ++--- src/feedbacks.js | 294 +++++++------- src/index.js | 96 ++--- src/presets.js | 882 ++++++++++++++++++++-------------------- src/socket.js | 392 +++++++++--------- src/state.js | 256 ++++++------ src/utils.js | 96 ++--- src/variables.js | 42 +- 14 files changed, 1522 insertions(+), 1522 deletions(-) diff --git a/companion/manifest.json b/companion/manifest.json index 969894d..6aebc38 100644 --- a/companion/manifest.json +++ b/companion/manifest.json @@ -1,35 +1,35 @@ { - "id": "stagetimerio-api", - "name": "stagetimer", - "shortname": "stagetimer", - "description": "Stagetimer.io module for Companion v3", - "version": "2.0.0", - "license": "MIT", - "repository": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git", - "bugs": "https://github.com/bitfocus/companion-module-stagetimerio-api/issues", - "maintainers": [ - { - "name": "Lukas Hermann", - "email": "lukas@stagetimer.io" - } - ], - "runtime": { - "type": "node18", - "api": "nodejs-ipc", - "apiVersion": "0.0.0", - "entrypoint": "../src/index.js" - }, - "legacyIds": [ - "hermann-stagetimerio" - ], - "manufacturer": "stagetimer.io", - "products": [ - "Stagetimer API" - ], - "keywords": [ - "Stagetimer", - "stagetimer.io", - "Timer", - "Companion" - ] -} \ No newline at end of file + "id": "stagetimerio-api", + "name": "stagetimer", + "shortname": "stagetimer", + "description": "Stagetimer.io module for Companion v3", + "version": "2.0.0", + "license": "MIT", + "repository": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git", + "bugs": "https://github.com/bitfocus/companion-module-stagetimerio-api/issues", + "maintainers": [ + { + "name": "Lukas Hermann", + "email": "lukas@stagetimer.io" + } + ], + "runtime": { + "type": "node18", + "api": "nodejs-ipc", + "apiVersion": "0.0.0", + "entrypoint": "../src/index.js" + }, + "legacyIds": [ + "hermann-stagetimerio" + ], + "manufacturer": "stagetimer.io", + "products": [ + "Stagetimer API" + ], + "keywords": [ + "Stagetimer", + "stagetimer.io", + "Timer", + "Companion" + ] +} diff --git a/jsconfig.json b/jsconfig.json index 9291050..99abdb2 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,9 +1,9 @@ { - "compilerOptions": { - "checkJs": true, - }, - "exclude": [ - "node_modules", - "**/node_modules/*" - ] -} \ No newline at end of file + "compilerOptions": { + "checkJs": true, + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} diff --git a/package.json b/package.json index d24fe7d..0ed1e65 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,22 @@ { - "name": "stagetimerio-api", - "version": "2.0.0", - "main": "src/index.js", - "type": "module", - "scripts": { - "lint": "eslint ./src" - }, - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git" - }, - "dependencies": { - "@companion-module/base": "~1.4.1", - "date-fns": "^2.30.0", - "socket.io-client": "^4.7.1" - }, - "devDependencies": { - "@companion-module/tools": "^1.3.2" - } -} \ No newline at end of file + "name": "stagetimerio-api", + "version": "2.0.0", + "main": "src/index.js", + "type": "module", + "scripts": { + "lint": "eslint ./src" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git" + }, + "dependencies": { + "@companion-module/base": "~1.4.1", + "date-fns": "^2.30.0", + "socket.io-client": "^4.7.1" + }, + "devDependencies": { + "@companion-module/tools": "^1.3.2" + } +} diff --git a/src/actions.js b/src/actions.js index f818890..89ac8b0 100644 --- a/src/actions.js +++ b/src/actions.js @@ -8,41 +8,41 @@ let instance = null * @enum {string} */ export const actionIdType = { - // Auth and status - test_auth: 'test_auth', - get_status: 'get_status', - get_room: 'get_room', + // Auth and status + test_auth: 'test_auth', + get_status: 'get_status', + get_room: 'get_room', - // Transport - start: 'start', - stop: 'stop', - start_or_stop: 'start_or_stop', - next: 'next', - previous: 'previous', - add_time: 'add_time', - subtract_time: 'subtract_time', + // Transport + start: 'start', + stop: 'stop', + start_or_stop: 'start_or_stop', + next: 'next', + previous: 'previous', + add_time: 'add_time', + subtract_time: 'subtract_time', - // Viewer - start_flashing: 'start_flashing', - stop_flashing: 'stop_flashing', - enable_blackout: 'enable_blackout', - disable_blackout: 'disable_blackout', - toggle_blackout: 'toggle_blackout', - enable_focus: 'enable_focus', - disable_focus: 'disable_focus', - toggle_focus: 'toggle_focus', + // Viewer + start_flashing: 'start_flashing', + stop_flashing: 'stop_flashing', + enable_blackout: 'enable_blackout', + disable_blackout: 'disable_blackout', + toggle_blackout: 'toggle_blackout', + enable_focus: 'enable_focus', + disable_focus: 'disable_focus', + toggle_focus: 'toggle_focus', - // Timer - start_timer: 'start_timer', - stop_timer: 'stop_timer', - start_or_stop_timer: 'start_or_stop_timer', - reset_timer: 'reset_timer', - get_timer: 'get_timer', + // Timer + start_timer: 'start_timer', + stop_timer: 'stop_timer', + start_or_stop_timer: 'start_or_stop_timer', + reset_timer: 'reset_timer', + get_timer: 'get_timer', - // Message - show_or_hide_message: 'show_or_hide_message', - show_message: 'show_message', - hide_message: 'hide_message', + // Message + show_or_hide_message: 'show_or_hide_message', + show_message: 'show_message', + hide_message: 'hide_message', } // Reusable labels @@ -55,70 +55,70 @@ let indexTip = 'Index of a timer or message to target in a room. Note: Index is * @type {Object.} */ const actionOptions = { - autostart: [ - { - id: 'autostart', - type: 'checkbox', - label: 'Autostart', - default: false, - tooltip: 'Set to `true` to automatically start the timer after the action is triggered.', - }, - ], - amount: [ - { - id: 'amount', - type: 'textinput', - label: 'Amount', - default: '1m', - required: true, - tooltip: 'An amount of time specified by a number followed by a divison of time. Eg. `5s` for 5 seconds, `10m` for 10 minutes, etc.', - }, - ], - count: [ - { - id: 'count', - type: 'number', - label: 'Count', - default: 3, - min: 1, - max: 999, - tooltip: 'Number of times to repeat the action. Accepted numbers: 1 - 999.', - }, - ], - timer: [ - { - id: 'index', - type: 'number', - label: 'Timer index', - default: 1, - min: 1, - max: 99, - tooltip: indexTip, - }, - { - id: 'timer_id', - type: 'textinput', - label: 'Timer ID', - tooltip: idTip + 'timer', - }, - ], - message: [ - { - id: 'index', - type: 'number', - label: 'Message index', - default: 1, - min: 1, - max: 99, - tooltip: indexTip, - }, - { - id: 'message_id', - type: 'textinput', - label: 'Message ID', - tooltip: idTip + 'message', - }, - ], + autostart: [ + { + id: 'autostart', + type: 'checkbox', + label: 'Autostart', + default: false, + tooltip: 'Set to `true` to automatically start the timer after the action is triggered.', + }, + ], + amount: [ + { + id: 'amount', + type: 'textinput', + label: 'Amount', + default: '1m', + required: true, + tooltip: 'An amount of time specified by a number followed by a divison of time. Eg. `5s` for 5 seconds, `10m` for 10 minutes, etc.', + }, + ], + count: [ + { + id: 'count', + type: 'number', + label: 'Count', + default: 3, + min: 1, + max: 999, + tooltip: 'Number of times to repeat the action. Accepted numbers: 1 - 999.', + }, + ], + timer: [ + { + id: 'index', + type: 'number', + label: 'Timer index', + default: 1, + min: 1, + max: 99, + tooltip: indexTip, + }, + { + id: 'timer_id', + type: 'textinput', + label: 'Timer ID', + tooltip: idTip + 'timer', + }, + ], + message: [ + { + id: 'index', + type: 'number', + label: 'Message index', + default: 1, + min: 1, + max: 99, + tooltip: indexTip, + }, + { + id: 'message_id', + type: 'textinput', + label: 'Message ID', + tooltip: idTip + 'message', + }, + ], } @@ -128,173 +128,173 @@ const actionOptions = { */ export function loadActions(theInstance) { - instance = theInstance + instance = theInstance - /** @type {CompanionActionDefinitions} */ - const all_actions = { + /** @type {CompanionActionDefinitions} */ + const all_actions = { - // Transport actions - [actionIdType.start]: { - name: 'Transport: Start', - description: 'Start or resume the highlighted timer in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.stop]: { - name: 'Transport: Stop', - description: 'Stop the highlighted timer in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.start_or_stop]: { - name: 'Transport: Start/stop', - description: 'Start/stop the highlighted timer in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.next]: { - name: 'Transport: Next', - description: 'Highlight the next timer in the list', - options: actionOptions.autostart, - callback: sendActionToApi, - }, - [actionIdType.previous]: { - name: 'Transport: Previous', - description: 'Reset the highlighted timer in the room if it is running. If the highlighted timer is not running, highlight the previous timer in the list. Optionally, you can automatically start the previous timer once it\'s highlighted.', - options: actionOptions.autostart, - callback: sendActionToApi, - }, - [actionIdType.add_time]: { - name: 'Transport: Add time', - description: 'Add an amount of time to the highlighted timer in the room.', - options: actionOptions.amount, - callback: sendActionToApi, - }, - [actionIdType.subtract_time]: { - name: 'Transport: Subtract time', - description: 'Subtract an amount of time from the highlighted timer in the room.', - options: actionOptions.amount, - callback: sendActionToApi, - }, + // Transport actions + [actionIdType.start]: { + name: 'Transport: Start', + description: 'Start or resume the highlighted timer in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.stop]: { + name: 'Transport: Stop', + description: 'Stop the highlighted timer in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.start_or_stop]: { + name: 'Transport: Start/stop', + description: 'Start/stop the highlighted timer in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.next]: { + name: 'Transport: Next', + description: 'Highlight the next timer in the list', + options: actionOptions.autostart, + callback: sendActionToApi, + }, + [actionIdType.previous]: { + name: 'Transport: Previous', + description: 'Reset the highlighted timer in the room if it is running. If the highlighted timer is not running, highlight the previous timer in the list. Optionally, you can automatically start the previous timer once it\'s highlighted.', + options: actionOptions.autostart, + callback: sendActionToApi, + }, + [actionIdType.add_time]: { + name: 'Transport: Add time', + description: 'Add an amount of time to the highlighted timer in the room.', + options: actionOptions.amount, + callback: sendActionToApi, + }, + [actionIdType.subtract_time]: { + name: 'Transport: Subtract time', + description: 'Subtract an amount of time from the highlighted timer in the room.', + options: actionOptions.amount, + callback: sendActionToApi, + }, - // Viewer actions - [actionIdType.start_flashing]: { - name: 'Viewer: Flash the screen', - description: 'Flashes the screen in the room. Can be used to grab the attention of speakers.', - options: actionOptions.count, - callback: sendActionToApi, - }, - [actionIdType.stop_flashing]: { - name: 'Viewer: Stop flashing', - description: 'Stops any flashing timers and message on the screen.', - options: [], - callback: sendActionToApi, - }, - [actionIdType.enable_blackout]: { - name: 'Viewer: Enable blackout mode', - description: 'Enable blackout mode in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.disable_blackout]: { - name: 'Viewer: Disable blackout mode', - description: 'Disable blackout mode in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.toggle_blackout]: { - name: 'Viewer: Toggle blackout mode', - description: 'Toggle (enable/disable) blackout mode in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.enable_focus]: { - name: 'Viewer: Enable focus mode', - description: 'Enable focus mode in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.disable_focus]: { - name: 'Viewer: Disable focus mode', - description: 'Disable focus mode in the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.toggle_focus]: { - name: 'Viewer: Toggle focus mode', - description: 'Toggle (enable/disable) focus mode in the room', - options: [], - callback: sendActionToApi, - }, + // Viewer actions + [actionIdType.start_flashing]: { + name: 'Viewer: Flash the screen', + description: 'Flashes the screen in the room. Can be used to grab the attention of speakers.', + options: actionOptions.count, + callback: sendActionToApi, + }, + [actionIdType.stop_flashing]: { + name: 'Viewer: Stop flashing', + description: 'Stops any flashing timers and message on the screen.', + options: [], + callback: sendActionToApi, + }, + [actionIdType.enable_blackout]: { + name: 'Viewer: Enable blackout mode', + description: 'Enable blackout mode in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.disable_blackout]: { + name: 'Viewer: Disable blackout mode', + description: 'Disable blackout mode in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.toggle_blackout]: { + name: 'Viewer: Toggle blackout mode', + description: 'Toggle (enable/disable) blackout mode in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.enable_focus]: { + name: 'Viewer: Enable focus mode', + description: 'Enable focus mode in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.disable_focus]: { + name: 'Viewer: Disable focus mode', + description: 'Disable focus mode in the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.toggle_focus]: { + name: 'Viewer: Toggle focus mode', + description: 'Toggle (enable/disable) focus mode in the room', + options: [], + callback: sendActionToApi, + }, - // Timer actions - [actionIdType.start_timer]: { - name: 'Timer: Start', - description: 'Start or resume a specific timer in the room', - options: actionOptions.timer, - callback: sendActionToApi, - }, - [actionIdType.stop_timer]: { - name: 'Timer: Stop', - description: 'Stop a specific timer in the room', - options: actionOptions.timer, - callback: sendActionToApi, - }, - [actionIdType.start_or_stop_timer]: { - name: 'Timer: Toggle playback', - description: 'Toggle (start/stop) a specific timer in the room', - options: actionOptions.timer, - callback: sendActionToApi, - }, - [actionIdType.reset_timer]: { - name: 'Timer: Reset', - description: 'Reset a specific timer to original duration', - options: actionOptions.timer, - callback: sendActionToApi, - }, + // Timer actions + [actionIdType.start_timer]: { + name: 'Timer: Start', + description: 'Start or resume a specific timer in the room', + options: actionOptions.timer, + callback: sendActionToApi, + }, + [actionIdType.stop_timer]: { + name: 'Timer: Stop', + description: 'Stop a specific timer in the room', + options: actionOptions.timer, + callback: sendActionToApi, + }, + [actionIdType.start_or_stop_timer]: { + name: 'Timer: Toggle playback', + description: 'Toggle (start/stop) a specific timer in the room', + options: actionOptions.timer, + callback: sendActionToApi, + }, + [actionIdType.reset_timer]: { + name: 'Timer: Reset', + description: 'Reset a specific timer to original duration', + options: actionOptions.timer, + callback: sendActionToApi, + }, - // Message actions - [actionIdType.show_message]: { - name: 'Message: Show', - description: 'Show a message in the room', - options: actionOptions.message, - callback: sendActionToApi, - }, - [actionIdType.hide_message]: { - name: 'Message: Hide', - description: 'Hide a message in the room', - options: actionOptions.message, - callback: sendActionToApi, - }, - [actionIdType.show_or_hide_message]: { - name: 'Message: Toggle visibility', - description: 'Show/hide a message in the room', - options: actionOptions.message, - callback: sendActionToApi, - }, + // Message actions + [actionIdType.show_message]: { + name: 'Message: Show', + description: 'Show a message in the room', + options: actionOptions.message, + callback: sendActionToApi, + }, + [actionIdType.hide_message]: { + name: 'Message: Hide', + description: 'Hide a message in the room', + options: actionOptions.message, + callback: sendActionToApi, + }, + [actionIdType.show_or_hide_message]: { + name: 'Message: Toggle visibility', + description: 'Show/hide a message in the room', + options: actionOptions.message, + callback: sendActionToApi, + }, - // Developer and utility actions - [actionIdType.test_auth]: { - name: 'Utility: Test auth', - description: 'Test connection and authentication', - options: [], - callback: sendActionToApi, - }, - [actionIdType.get_status]: { - name: 'Utility: Get status', - description: 'Get playback status of the room', - options: [], - callback: sendActionToApi, - }, - [actionIdType.get_room]: { - name: 'Utility: Get room', - description: 'Get status of the room', - options: [], - callback: sendActionToApi, - }, - } + // Developer and utility actions + [actionIdType.test_auth]: { + name: 'Utility: Test auth', + description: 'Test connection and authentication', + options: [], + callback: sendActionToApi, + }, + [actionIdType.get_status]: { + name: 'Utility: Get status', + description: 'Get playback status of the room', + options: [], + callback: sendActionToApi, + }, + [actionIdType.get_room]: { + name: 'Utility: Get room', + description: 'Get status of the room', + options: [], + callback: sendActionToApi, + }, + } - instance.setActionDefinitions(all_actions) + instance.setActionDefinitions(all_actions) } /** @@ -305,22 +305,22 @@ export function loadActions(theInstance) { */ const sendActionToApi = async ({ actionId, options }) => { - instance.log('debug', `Action: ${actionId}`) + instance.log('debug', `Action: ${actionId}`) - if (actionId in actionIdType === false) { - // Prevent actionId's not allowed by HTTP API - throw new Error('Not a valid actionId') - } + if (actionId in actionIdType === false) { + // Prevent actionId's not allowed by HTTP API + throw new Error('Not a valid actionId') + } - const params = assignTruthyOptionsToParams(options) + const params = assignTruthyOptionsToParams(options) - try { - const { message } = await instance.apiClient.send(actionId, params) + try { + const { message } = await instance.apiClient.send(actionId, params) - instance.log('debug', `API response: ${message}`) - } catch (error) { - instance.log('error', error.toString()) - } + instance.log('debug', `API response: ${message}`) + } catch (error) { + instance.log('error', error.toString()) + } } /** @@ -332,8 +332,8 @@ const sendActionToApi = async ({ actionId, options }) => { */ function assignTruthyOptionsToParams(options) { - return Object.fromEntries( - Object.entries(options).filter(([_key, value]) => value) - ) + return Object.fromEntries( + Object.entries(options).filter(([_key, value]) => value) + ) } diff --git a/src/api.js b/src/api.js index 497f54b..853ca49 100644 --- a/src/api.js +++ b/src/api.js @@ -1,26 +1,26 @@ // Custom error class NetworkError extends Error { - get name() { - return this.constructor.name - } + get name() { + return this.constructor.name + } } class HttpError extends Error { - /** @param {Response} response */ - constructor(response) { - super(`${response.status} ${response.statusText}`) - } + /** @param {Response} response */ + constructor(response) { + super(`${response.status} ${response.statusText}`) + } - get name() { - return this.constructor.name - } + get name() { + return this.constructor.name + } } class ApiError extends Error { - get name() { - return this.constructor.name - } + get name() { + return this.constructor.name + } } /** @@ -28,72 +28,72 @@ class ApiError extends Error { */ export class ApiClient { - /** - * API Client constructor. Configured with the same - * API URL, key, and room ID from the module config - * - * @param {StagetimerConfig} config - */ - constructor(config) { - this.apiUrl = config.apiUrl - this.apiKey = config.apiKey - this.roomId = config.roomId - return this - } - - /** - * Sends an action to the Stagetimer API - * - * @param {string} path - * @param {object} queryParams - * @returns {Promise} - */ - async send(path = '', queryParams = {}) { - try { - - const params = { - room_id: this.roomId, - api_key: this.apiKey, - ...queryParams, - } - - let query = '' - query = new URLSearchParams(params).toString() - query = query && `?${query}` - - const url = `${this.apiUrl}${path}${query}` - - const response = await fetch(url, { - // Time out before the default Companion IPC action timeout - signal: AbortSignal.timeout(4900) - }) - - if (!response.ok) { - - // Handle both JSON and non-JSON response body - const maybeJSON = await response.json().catch(() => { - throw new HttpError(response) - }) - - throw new ApiError(maybeJSON.message) - } - - return await response.json() - - } catch (error) { - switch (error.name) { - // Handle the timeout with a friendly message - case 'TimeoutError': - throw new NetworkError('Request took longer than 5s and timed out') - - // fetch() throws TypeError on network problems - case 'TypeError': - throw new NetworkError('There is a problem with the connection') - - // Pass errors through - default: - throw error - } - } - } + /** + * API Client constructor. Configured with the same + * API URL, key, and room ID from the module config + * + * @param {StagetimerConfig} config + */ + constructor(config) { + this.apiUrl = config.apiUrl + this.apiKey = config.apiKey + this.roomId = config.roomId + return this + } + + /** + * Sends an action to the Stagetimer API + * + * @param {string} path + * @param {object} queryParams + * @returns {Promise} + */ + async send(path = '', queryParams = {}) { + try { + + const params = { + room_id: this.roomId, + api_key: this.apiKey, + ...queryParams, + } + + let query = '' + query = new URLSearchParams(params).toString() + query = query && `?${query}` + + const url = `${this.apiUrl}${path}${query}` + + const response = await fetch(url, { + // Time out before the default Companion IPC action timeout + signal: AbortSignal.timeout(4900) + }) + + if (!response.ok) { + + // Handle both JSON and non-JSON response body + const maybeJSON = await response.json().catch(() => { + throw new HttpError(response) + }) + + throw new ApiError(maybeJSON.message) + } + + return await response.json() + + } catch (error) { + switch (error.name) { + // Handle the timeout with a friendly message + case 'TimeoutError': + throw new NetworkError('Request took longer than 5s and timed out') + + // fetch() throws TypeError on network problems + case 'TypeError': + throw new NetworkError('There is a problem with the connection') + + // Pass errors through + default: + throw error + } + } + } } diff --git a/src/assets.js b/src/assets.js index bdc7a07..daba39d 100644 --- a/src/assets.js +++ b/src/assets.js @@ -1,39 +1,39 @@ import { combineRgb } from '@companion-module/base' export const colors = { - black: combineRgb(0, 0, 0), - white: combineRgb(255, 255, 255), - green: combineRgb(0, 255, 0), - red: combineRgb(250, 42, 42), - yellow: combineRgb(255, 169, 0), - lightGreen: combineRgb(127, 252, 127), - lightRed: combineRgb(255, 166, 166), - lightGray: combineRgb(180, 180, 180), - lightBlue: combineRgb(127, 213, 252), + black: combineRgb(0, 0, 0), + white: combineRgb(255, 255, 255), + green: combineRgb(0, 255, 0), + red: combineRgb(250, 42, 42), + yellow: combineRgb(255, 169, 0), + lightGreen: combineRgb(127, 252, 127), + lightRed: combineRgb(255, 166, 166), + lightGray: combineRgb(180, 180, 180), + lightBlue: combineRgb(127, 213, 252), } export const icons = { - // Transport - play: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcH+Aj5Cfr8DP3+8H0QoWAAAAkklEQVRYw+2VQQ7CMAwEm1KgaaHE8//HcgGJiGPmgITnASOvbK2nKUlGWSNus2bbANrF0gUAPKQBebMWVeck5gNhJXSsro52VnWjib90tKuqgzarOthcHdXVxU/rdlW3m6s4FvFQQj3jezErYBErIGoRC+ow63M0Z6+ryut5Pcbj5DzGOnxqPXuEkzNJkiRJ/pMnMJAdaP3cKN8AAAAASUVORK5CYII=', - pause: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAFVBMVEUAAAD///////////////////////9Iz20EAAAABnRSTlMAf4CPkO9T4O/6AAAASklEQVRIx2NgGAWEgWhaWlowEo0DMKeBgAKcxgVYwfIBcBoXYAPLJ8DpUXWj6kbV0U4dsfmSCSzvAKdxAlegdBASPQpGwSgYzAAAZ4iCBcCPC08AAAAASUVORK5CYII=', - playPause: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcH+Aj5Cfr8DP3+8H0QoWAAAAuUlEQVRYw+2VwQ6CQAwFAVFZUNzO/3+sB8Eg2zUxvIOHzq3pZkjT0jZNEPzKYHbraikAsNGPHUaAfKmmXiQv9lg++OiqKQDzYo/3i6GtpgAv/qorKz6mg11Ljupg0OrIZ6luW7FER75KdZA7qQ5GrY6k1dlf6yapblK2Yu6Fg2LSMb63yhXQC1eApVa4oGbl+tzWeVyXJKdnuXbzSXMY08eolanNX7KPXSazss41tTbcj4MgCIIgKHkCGPJLgnb63zkAAAAASUVORK5CYII=', - previous: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwX2B/gJ+gr8/f7+JXqNEAAACNSURBVEjHY2AYBUQAnndPwTTLHQe86vjePQfTee8uEKOO7d27B8SoyyNOHcc7otQx9hGnTvodUeqY9hGnTucdUeqYzhGnzuYdUepe3SNOHQwMVnWvifTHc9t31A1nYuONAWIgEelKm0h1jOuIU8fASaQ6hjoi1bETqQ5o4AGiyg3WswGjhegoGAWDHQAAVOC9PWOv8FAAAAAASUVORK5CYII=', - next: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwX2B/gJ+gr8/f7+JXqNEAAACKSURBVEjHY2AYBUQAljsOYDru3QG86njePQPTde8e4FXH9+5dApHqnhGp7l0DkepeCRCn7t0mItW9USBO3btDRKp7o0CcuneXiVT3dh9x6oBgUKt7u444dYepG85ExttrItPBRuLS1Usi0+kE4tL9cyLzUQEx6nghxhFUx3o2gKhyYxSMglEwCAAAqoW942zpZV4AAAAASUVORK5CYII=', + // Transport + play: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcH+Aj5Cfr8DP3+8H0QoWAAAAkklEQVRYw+2VQQ7CMAwEm1KgaaHE8//HcgGJiGPmgITnASOvbK2nKUlGWSNus2bbANrF0gUAPKQBebMWVeck5gNhJXSsro52VnWjib90tKuqgzarOthcHdXVxU/rdlW3m6s4FvFQQj3jezErYBErIGoRC+ow63M0Z6+ryut5Pcbj5DzGOnxqPXuEkzNJkiRJ/pMnMJAdaP3cKN8AAAAASUVORK5CYII=', + pause: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAFVBMVEUAAAD///////////////////////9Iz20EAAAABnRSTlMAf4CPkO9T4O/6AAAASklEQVRIx2NgGAWEgWhaWlowEo0DMKeBgAKcxgVYwfIBcBoXYAPLJ8DpUXWj6kbV0U4dsfmSCSzvAKdxAlegdBASPQpGwSgYzAAAZ4iCBcCPC08AAAAASUVORK5CYII=', + playPause: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcH+Aj5Cfr8DP3+8H0QoWAAAAuUlEQVRYw+2VwQ6CQAwFAVFZUNzO/3+sB8Eg2zUxvIOHzq3pZkjT0jZNEPzKYHbraikAsNGPHUaAfKmmXiQv9lg++OiqKQDzYo/3i6GtpgAv/qorKz6mg11Ljupg0OrIZ6luW7FER75KdZA7qQ5GrY6k1dlf6yapblK2Yu6Fg2LSMb63yhXQC1eApVa4oGbl+tzWeVyXJKdnuXbzSXMY08eolanNX7KPXSazss41tTbcj4MgCIIgKHkCGPJLgnb63zkAAAAASUVORK5CYII=', + previous: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwX2B/gJ+gr8/f7+JXqNEAAACNSURBVEjHY2AYBUQAnndPwTTLHQe86vjePQfTee8uEKOO7d27B8SoyyNOHcc7otQx9hGnTvodUeqY9hGnTucdUeqYzhGnzuYdUepe3SNOHQwMVnWvifTHc9t31A1nYuONAWIgEelKm0h1jOuIU8fASaQ6hjoi1bETqQ5o4AGiyg3WswGjhegoGAWDHQAAVOC9PWOv8FAAAAAASUVORK5CYII=', + next: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwX2B/gJ+gr8/f7+JXqNEAAACKSURBVEjHY2AYBUQAljsOYDru3QG86njePQPTde8e4FXH9+5dApHqnhGp7l0DkepeCRCn7t0mItW9USBO3btDRKp7o0CcuneXiVT3dh9x6oBgUKt7u444dYepG85ExttrItPBRuLS1Usi0+kE4tL9cyLzUQEx6nghxhFUx3o2gKhyYxSMglEwCAAAqoW942zpZV4AAAAASUVORK5CYII=', - // Viewer - flash: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECAwQFBgcICQn6Cwv8DP3+Dvv0cgUAAAAJ1JREFUGBntwcGSgjAURNEmE2NAkYz3//91wAGrcGell+8cheCQGrs2qF/mLavflUOTwchhksGdQ5bBwq7J4cluksHAIcsgs3vmf+py4UNRj8qHoh43zpq6zJwVdfnlZFIfzpL61MfLwssoj8KmJXnc2BSZLKyaTBKbH5lcWE1yGVklucxAlcsANNlkoMimwiKfGZJ8rlSFEEII4Xt/66gShOCllwcAAAAASUVORK5CYII=', - flashOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+wv8/f7/yCZEUAAADfSURBVBgZ7cHRkoIwEATAyV4kRpCDcf7/W29RUPTlqlgf042mCUik4c6oFROOukjMWGQ9ZRxFuTNc0YY4zCg3GtBrMyCgl6PhV5uMiKJFmbUiYozaGxBko3YywqqebvkBEZn60CHCZr3rEFO1R0R1N710CDNqMyBmSADSVStDTL1iUXXX40t+KHfBt9gkNxu+pcoxI84y3IlyZ4SddIYzyo2GoF4aDUDq5WiImSQVLIoWBRFJEvFglLsgIEvqsLJRjobDqjTjpcoRh02SYSdT6nFYUcUbIxOapmmapvnHHye0F8UklMnjAAAAAElFTkSuQmCC', - blackout: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECAwQFBgcH+Aj5CfoLC/z9/vtr8TOgAAAKdJREFUGBntwct2AiEUBMDmIQwhDEL//7/GCBq3OdPLWwVjRFzud8gckwwQ8YNkgUiYJAdEwuRDgoYffBgQafz1DY3Ipxs0Tj4FSHguHhI3Lg4ShYuHROMSIdG5ZEg0Lh0SlZuDQuZWoOC5TQ+Fzq1DIfPlgIAbfDkgEPn2BYHKt5FwXeOfkTyuKvw0ey+4JA1+qg4XpcFt1giBkOt5thwdjDHGGPMPP86rESH39+l5AAAAAElFTkSuQmCC', - blackoutOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+wv8/f7/yCZEUAAAD4SURBVFjD7ZXBkoMgEAUBUVRi1KH//1v3QCKbXFLlzJG+cemqB28G5zqd+3iR0A7pOHW6FSS+ZHOBQacTgNk554IAizJsEIBncLEAor+9DCBjAZgMXiPxRkxetwYGHjZtCc+qG63qtwCQzOocW2NsAp8ARzBQTeEKLINet1fJVGwCH//njIdX6ra3xG8AEizmrF1gmQzGrEoGfWPCa8jqBR4AZ9C9BU1SGxMNlkqVjMrAXq4lNX8s1bsjy6fPZ11jcvNVSdLtmK35SmqBV93Kq6xtqd4OPMl34EX3gTRhzeuiQFb0eUh537cU/fUriXedTqfT6XR+8Ae+ExfsQGxVnAAAAABJRU5ErkJggg==', - focus: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcICQn6Cvv8DP3+/6FJslAAAAzElEQVRYw+3V2w6DIBRE0cNFRLQK8/8f2yqYtIlNWpzHs98McUUFQUTT7jVmXLaFHi3ga2MHtyFeD0TkDg74f+RnLsS9gcTZ+tEK6+nm6rE4WaicK0yuaQTONq24mcAFpKaJTONtLgJL0xjLONYF54TJOaFyict97C53OM/leBuUuR4wXdwDi68d02rahR8S1g7u/E1x3O3ezqFie84eO697286NBXltTV3amcdqEjAZznHrkTNKEGFxr5PaCpFjvWid4SCapmmapvX0BPnlE5sWA4rIAAAAAElFTkSuQmCC', - focusOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAAEcSURBVFjD7ZbbEoMgDEQJKNR6h/z/t7YQrKW10zHxkX1TJmfcsASVqqpiC7zXynk81GrP4u6Ivsefcidx9F3d8WKH/iROJ96kj1cRT3cvWfU7z3ZRLRenXNElTU0LbFw2fM9PI/H4OKWnd8OTFBf3MPJSzEyQ41STDN9eNAHulgyvETK3T1owowSH8244bqp5pscJcLnIkk8jivFbESVmgItwCsbyiAhxuYHBXoBzFLstMVJcQxA9p8mpLzG7H5GGj4PyRZsNAws349SQTDlUB1wYuO2YYqo2sWtA90fQrAE1LlFrxLlAsXOsq6eYKrjAgNjDwVBl4bzfI/wxVDm4LW9FYgS4Hr6Gas/FmWC/byUP9c+rqqqqqqrqrx5WNhsy/NzpFQAAAABJRU5ErkJggg==', + // Viewer + flash: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECAwQFBgcICQn6Cwv8DP3+Dvv0cgUAAAAJ1JREFUGBntwcGSgjAURNEmE2NAkYz3//91wAGrcGell+8cheCQGrs2qF/mLavflUOTwchhksGdQ5bBwq7J4cluksHAIcsgs3vmf+py4UNRj8qHoh43zpq6zJwVdfnlZFIfzpL61MfLwssoj8KmJXnc2BSZLKyaTBKbH5lcWE1yGVklucxAlcsANNlkoMimwiKfGZJ8rlSFEEII4Xt/66gShOCllwcAAAAASUVORK5CYII=', + flashOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+wv8/f7/yCZEUAAADfSURBVBgZ7cHRkoIwEATAyV4kRpCDcf7/W29RUPTlqlgf042mCUik4c6oFROOukjMWGQ9ZRxFuTNc0YY4zCg3GtBrMyCgl6PhV5uMiKJFmbUiYozaGxBko3YywqqebvkBEZn60CHCZr3rEFO1R0R1N710CDNqMyBmSADSVStDTL1iUXXX40t+KHfBt9gkNxu+pcoxI84y3IlyZ4SddIYzyo2GoF4aDUDq5WiImSQVLIoWBRFJEvFglLsgIEvqsLJRjobDqjTjpcoRh02SYSdT6nFYUcUbIxOapmmapvnHHye0F8UklMnjAAAAAElFTkSuQmCC', + blackout: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECAwQFBgcH+Aj5CfoLC/z9/vtr8TOgAAAKdJREFUGBntwct2AiEUBMDmIQwhDEL//7/GCBq3OdPLWwVjRFzud8gckwwQ8YNkgUiYJAdEwuRDgoYffBgQafz1DY3Ipxs0Tj4FSHguHhI3Lg4ShYuHROMSIdG5ZEg0Lh0SlZuDQuZWoOC5TQ+Fzq1DIfPlgIAbfDkgEPn2BYHKt5FwXeOfkTyuKvw0ey+4JA1+qg4XpcFt1giBkOt5thwdjDHGGPMPP86rESH39+l5AAAAAElFTkSuQmCC', + blackoutOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+wv8/f7/yCZEUAAAD4SURBVFjD7ZXBkoMgEAUBUVRi1KH//1v3QCKbXFLlzJG+cemqB28G5zqd+3iR0A7pOHW6FSS+ZHOBQacTgNk554IAizJsEIBncLEAor+9DCBjAZgMXiPxRkxetwYGHjZtCc+qG63qtwCQzOocW2NsAp8ARzBQTeEKLINet1fJVGwCH//njIdX6ra3xG8AEizmrF1gmQzGrEoGfWPCa8jqBR4AZ9C9BU1SGxMNlkqVjMrAXq4lNX8s1bsjy6fPZ11jcvNVSdLtmK35SmqBV93Kq6xtqd4OPMl34EX3gTRhzeuiQFb0eUh537cU/fUriXedTqfT6XR+8Ae+ExfsQGxVnAAAAABJRU5ErkJggg==', + focus: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOVBMVEUAAAD///////////////////////////////////////////////////////////////////////8KOjVvAAAAEnRSTlMAECAwQFBgcICQn6Cvv8DP3+/6FJslAAAAzElEQVRYw+3V2w6DIBRE0cNFRLQK8/8f2yqYtIlNWpzHs98McUUFQUTT7jVmXLaFHi3ga2MHtyFeD0TkDg74f+RnLsS9gcTZ+tEK6+nm6rE4WaicK0yuaQTONq24mcAFpKaJTONtLgJL0xjLONYF54TJOaFyict97C53OM/leBuUuR4wXdwDi68d02rahR8S1g7u/E1x3O3ezqFie84eO697286NBXltTV3amcdqEjAZznHrkTNKEGFxr5PaCpFjvWid4SCapmmapvX0BPnlE5sWA4rIAAAAAElFTkSuQmCC', + focusOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAAEcSURBVFjD7ZbbEoMgDEQJKNR6h/z/t7YQrKW10zHxkX1TJmfcsASVqqpiC7zXynk81GrP4u6Ivsefcidx9F3d8WKH/iROJ96kj1cRT3cvWfU7z3ZRLRenXNElTU0LbFw2fM9PI/H4OKWnd8OTFBf3MPJSzEyQ41STDN9eNAHulgyvETK3T1owowSH8244bqp5pscJcLnIkk8jivFbESVmgItwCsbyiAhxuYHBXoBzFLstMVJcQxA9p8mpLzG7H5GGj4PyRZsNAws349SQTDlUB1wYuO2YYqo2sWtA90fQrAE1LlFrxLlAsXOsq6eYKrjAgNjDwVBl4bzfI/wxVDm4LW9FYgS4Hr6Gas/FmWC/byUP9c+rqqqqqqrqrx5WNhsy/NzpFQAAAABJRU5ErkJggg==', - // Timer - timer: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECBAUGBwf4CQn6Cwv8DP0N/vGoQcGAAAARFJREFUWMPtlstuhDAMRZ2Ex4SZTBqf///XLkIZKEiVTHbNXUUgH2xzsRHp6mqmETTF0Ar3AIAyNsNpBfpGuEXCE9DBThn8HifiC2Dmef2pbcXVqq31FphWcAiuniIkszvy+WqC0ZqcFxnzsTgPxUILtV+u/HLbCyx+jmtYgMUdHxMNuAT1MB3d6/SqpX/qE5WA+XMjowYcvDf/Acmd0jbiZIDNglbcvkUReNwrdh/lXrz9RdoGo1z4MdptfNLTZmNRuBge1o9MpsvhYR4Bkg/urZqtyVX7zieaeXzKCKRdtE93hrvIoMCyvsi6em7tRl8ANKWUFSDfXYxjYZNODZZsiG8F/Wr3U9HV1dXV1fVP9A0dvxCm3WkvCAAAAABJRU5ErkJggg==', - timerOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+Aj5CfoK+wv8DP0N/vTWO0pgAAATdJREFUWMPtlstuwzAMBClFcR5yUsUV5/8/tQe1sewEKLJn7c0GNOZS5MJmQ0O6Qq1xfZrAS0467gp1PX4BgDqpuApw7nDegFHDxQJwj0/cbOkG+FGs79JVc4HZzGIFVN6xApw6XHMt+m3FcA1mMaXQ3mUo8v3m1/YXkO/XTgC1b1eEqpAOx9XwuXv/BUkyejYzi3eAshpOkAVcgX5iDs/1cxYBt55KW8MLLuDg8Wz/AjCHXdkqbrsiGm7boskBn3Szu1PrxGzK/mQjNvMVbgBLFAcl/a39roFFG2Nz2IXHobYMVfe1vA3VokXUsl3Wl4n5NO/8Da8L1U817ZyFLlSlfHdg/r3IdPuFZNlwK8VLKYsD3LtQle5jasMBgJ+6r2TTlPLDwb/7n4pYaxh/XkNDQ0NDQ//pB1yLGkgS62hVAAAAAElFTkSuQmCC', - timerReset: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+AkJ+gr7C/wM/Q3+Dvlll16gAAAT1JREFUWMPtll1vwyAMRS+U0nx0I4z6/P+fuofQrlorTXLyttwnhOQTXzB2pEOHdlMGK1PaCzcCQMu74WwFxp1ws9IVsLOfco7POCk2wM2LdvfWcatrr98Glw5OKayrCYq7OurrboHsTe6NrwjNQ0v38/qlT/DU89TD8keZoxSGWnL/zOTAFZCkATOKVLH1ZoK9O9I/1aOMGIyUaCFhQVLFHDhYJCWaNDGOTNKN00/aftzIfGWUbiQ3bjV7z25as0tus2tUgKBCzhRFCI+0nYVSqFdaDMZcmf2F0ss4LtBO0qnBEiVdfWUs648s9KcWw5ZHpsvb5uFuAaow/N4bvMlJ0V54w4b2qQyUp+hYtjR36WzA3C9yHT2bZmNsAFZKqQZQtw7G3HjILjsM2TQtBva130/FoUOHDh069E/0DUb+Fu6sLuw3AAAAAElFTkSuQmCC', + // Timer + timer: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECBAUGBwf4CQn6Cwv8DP0N/vGoQcGAAAARFJREFUWMPtlstuhDAMRZ2Ex4SZTBqf///XLkIZKEiVTHbNXUUgH2xzsRHp6mqmETTF0Ar3AIAyNsNpBfpGuEXCE9DBThn8HifiC2Dmef2pbcXVqq31FphWcAiuniIkszvy+WqC0ZqcFxnzsTgPxUILtV+u/HLbCyx+jmtYgMUdHxMNuAT1MB3d6/SqpX/qE5WA+XMjowYcvDf/Acmd0jbiZIDNglbcvkUReNwrdh/lXrz9RdoGo1z4MdptfNLTZmNRuBge1o9MpsvhYR4Bkg/urZqtyVX7zieaeXzKCKRdtE93hrvIoMCyvsi6em7tRl8ANKWUFSDfXYxjYZNODZZsiG8F/Wr3U9HV1dXV1fVP9A0dvxCm3WkvCAAAAABJRU5ErkJggg==', + timerOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+Aj5CfoK+wv8DP0N/vTWO0pgAAATdJREFUWMPtlstuwzAMBClFcR5yUsUV5/8/tQe1sewEKLJn7c0GNOZS5MJmQ0O6Qq1xfZrAS0467gp1PX4BgDqpuApw7nDegFHDxQJwj0/cbOkG+FGs79JVc4HZzGIFVN6xApw6XHMt+m3FcA1mMaXQ3mUo8v3m1/YXkO/XTgC1b1eEqpAOx9XwuXv/BUkyejYzi3eAshpOkAVcgX5iDs/1cxYBt55KW8MLLuDg8Wz/AjCHXdkqbrsiGm7boskBn3Szu1PrxGzK/mQjNvMVbgBLFAcl/a39roFFG2Nz2IXHobYMVfe1vA3VokXUsl3Wl4n5NO/8Da8L1U817ZyFLlSlfHdg/r3IdPuFZNlwK8VLKYsD3LtQle5jasMBgJ+6r2TTlPLDwb/7n4pYaxh/XkNDQ0NDQ//pB1yLGkgS62hVAAAAAElFTkSuQmCC', + timerReset: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+AkJ+gr7C/wM/Q3+Dvlll16gAAAT1JREFUWMPtll1vwyAMRS+U0nx0I4z6/P+fuofQrlorTXLyttwnhOQTXzB2pEOHdlMGK1PaCzcCQMu74WwFxp1ws9IVsLOfco7POCk2wM2LdvfWcatrr98Glw5OKayrCYq7OurrboHsTe6NrwjNQ0v38/qlT/DU89TD8keZoxSGWnL/zOTAFZCkATOKVLH1ZoK9O9I/1aOMGIyUaCFhQVLFHDhYJCWaNDGOTNKN00/aftzIfGWUbiQ3bjV7z25as0tus2tUgKBCzhRFCI+0nYVSqFdaDMZcmf2F0ss4LtBO0qnBEiVdfWUs648s9KcWw5ZHpsvb5uFuAaow/N4bvMlJ0V54w4b2qQyUp+hYtjR36WzA3C9yHT2bZmNsAFZKqQZQtw7G3HjILjsM2TQtBva130/FoUOHDh069E/0DUb+Fu6sLuw3AAAAAElFTkSuQmCC', - // Message - message: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwQGBwkKC/wM/f7/7VrqgAAABrSURBVEjHY2AYBYRBzjsE2IpbGes7ZJCAUx03iroDONXxoah7MKpuVN2gVMeJom4BTnXM95CUvVXAnZE0Vq1aDVTyZhUQFOHPmixAdYVEZGGguqsMRKl7rUCcukKiig7mq6PF5ygYBUMEAACZJi4Vt/I3cwAAAABJRU5ErkJggg==', - messageOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAADcSURBVFjD7dbRDoIwDAXQu6JDRWTr+v/f6gOaMBEIXR97P+AkbZq7AR6POoGZ0LP8TY5nuYcID7KZ/iTHshs+ydGBd3p7gy2H3pbbHVhzLfQy5YC7LYcLm3E3AKBsxclEmwNrOOEOAGIx4kRuGxej5OQZAITRihP+u0A1JyUCQMdG3HeBkxUneTVwEyd8AYArt3DVdPXFJAXXVef7JABhLtVCqoIaU0op5eXF9Kqnp2qVmRvColQfjVyJdakytXCZfkuVG7jPoMtSHbRcV+L6VeLgPy+Px+PxeA7zBmxuLz3gMRqIAAAAAElFTkSuQmCC', + // Message + message: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwQGBwkKC/wM/f7/7VrqgAAABrSURBVEjHY2AYBYRBzjsE2IpbGes7ZJCAUx03iroDONXxoah7MKpuVN2gVMeJom4BTnXM95CUvVXAnZE0Vq1aDVTyZhUQFOHPmixAdYVEZGGguqsMRKl7rUCcukKiig7mq6PF5ygYBUMEAACZJi4Vt/I3cwAAAABJRU5ErkJggg==', + messageOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAADcSURBVFjD7dbRDoIwDAXQu6JDRWTr+v/f6gOaMBEIXR97P+AkbZq7AR6POoGZ0LP8TY5nuYcID7KZ/iTHshs+ydGBd3p7gy2H3pbbHVhzLfQy5YC7LYcLm3E3AKBsxclEmwNrOOEOAGIx4kRuGxej5OQZAITRihP+u0A1JyUCQMdG3HeBkxUneTVwEyd8AYArt3DVdPXFJAXXVef7JABhLtVCqoIaU0op5eXF9Kqnp2qVmRvColQfjVyJdakytXCZfkuVG7jPoMtSHbRcV+L6VeLgPy+Px+PxeA7zBmxuLz3gMRqIAAAAAElFTkSuQmCC', } diff --git a/src/config.js b/src/config.js index c41af1e..0b54ab2 100644 --- a/src/config.js +++ b/src/config.js @@ -5,9 +5,9 @@ const apiUrlRegExp = /^https?:\/\/.*(\/v1\/)$/ /** @type {StagetimerConfig} */ export const initialConfig = { - roomId: '', - apiKey: '', - apiUrl: '', + roomId: '', + apiKey: '', + apiUrl: '', } /** @@ -17,58 +17,58 @@ export const initialConfig = { */ export function validateConfig(config) { - if ( - roomIdRegExp.test(config.roomId) - && apiKeyRegExp.test(config.apiKey) - && apiUrlRegExp.test(config.apiUrl) - ) { - return true - } + if ( + roomIdRegExp.test(config.roomId) + && apiKeyRegExp.test(config.apiKey) + && apiUrlRegExp.test(config.apiUrl) + ) { + return true + } - throw new Error('Bad configuration! Please review module settings and try again.') + throw new Error('Bad configuration! Please review module settings and try again.') } /** * @type { SomeCompanionConfigField[] } */ export const configFields = [ - { - type: 'static-text', - width: 12, - id: 'info', - label: 'Information', - value: ` - Remotely control Stagetimer.io using Companion.

- Requires a Stagetimer.io account on a paid plan (Pro or Premium).

- Enter your Room ID and API key below to get started.
- You can generate an API key on the controller page. - `, - }, - { - type: 'textinput', - width: 4, - id: 'roomId', - label: 'Room ID', - regex: roomIdRegExp.toString(), - required: true, - default: 'YOUR-ID', - }, - { - type: 'textinput', - width: 8, - id: 'apiKey', - label: 'API Key', - regex: apiKeyRegExp.toString(), - required: true, - default: 'YOUR-KEY', - }, - { - type: 'textinput', - width: 12, - id: 'apiUrl', - label: 'API URL', - regex: apiUrlRegExp.toString(), - required: true, - default: 'https://api.stagetimer.io/v1/', - }, + { + type: 'static-text', + width: 12, + id: 'info', + label: 'Information', + value: ` + Remotely control Stagetimer.io using Companion.

+ Requires a Stagetimer.io account on a paid plan (Pro or Premium).

+ Enter your Room ID and API key below to get started.
+ You can generate an API key on the controller page. + `, + }, + { + type: 'textinput', + width: 4, + id: 'roomId', + label: 'Room ID', + regex: roomIdRegExp.toString(), + required: true, + default: 'YOUR-ID', + }, + { + type: 'textinput', + width: 8, + id: 'apiKey', + label: 'API Key', + regex: apiKeyRegExp.toString(), + required: true, + default: 'YOUR-KEY', + }, + { + type: 'textinput', + width: 12, + id: 'apiUrl', + label: 'API URL', + regex: apiUrlRegExp.toString(), + required: true, + default: 'https://api.stagetimer.io/v1/', + }, ] diff --git a/src/feedbacks.js b/src/feedbacks.js index ca3aa78..4a79b50 100644 --- a/src/feedbacks.js +++ b/src/feedbacks.js @@ -13,16 +13,16 @@ export let feedbacks = {} * @enum {string} */ export const feedbackType = { - isRunning: 'isRunning', - isStopped: 'isStopped', - isOnTime: 'isOnTime', - isOverTime: 'isOverTime', - isWarningYellow: 'isYellowPhase', - isWarningRed: 'isRedPhase', - isFlashing: 'isFlashing', - blackoutEnabled: 'blackoutEnabled', - focusEnabled: 'focusEnabled', - messageIsShowing: 'messageIsShowing', + isRunning: 'isRunning', + isStopped: 'isStopped', + isOnTime: 'isOnTime', + isOverTime: 'isOverTime', + isWarningYellow: 'isYellowPhase', + isWarningRed: 'isRedPhase', + isFlashing: 'isFlashing', + blackoutEnabled: 'blackoutEnabled', + focusEnabled: 'focusEnabled', + messageIsShowing: 'messageIsShowing', } /** @@ -31,140 +31,140 @@ export const feedbackType = { */ function generateFeedbacks(instance) { - feedbacks = { - - [feedbackType.isRunning]: { - name: 'Playback running', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return instance.state.playback_status.isRunning - }, - }, - - [feedbackType.isStopped]: { - name: 'Playback stopped', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return !instance.state.playback_status.isRunning - }, - }, - - [feedbackType.isOnTime]: { - name: 'Timer is running and on time', - type: 'boolean', - defaultStyle: { - color: colors.green, - }, - options: [], - callback: (_feedback) => { - let { phase, isRunning } = instance.state.playback_status - return phase == timerPhases.default && isRunning - }, - }, - - [feedbackType.isOverTime]: { - name: 'Timer is over time', - type: 'boolean', - defaultStyle: { - color: colors.red, - }, - options: [], - callback: (_feedback) => { - let { phase } = instance.state.playback_status - return phase == timerPhases.negative - }, - }, - - [feedbackType.isWarningYellow]: { - name: 'Timer is showing yellow wrap-up warning', - type: 'boolean', - defaultStyle: { - color: colors.yellow, - }, - options: [], - callback: (_feedback) => { - let { phase } = instance.state.playback_status - return phase == timerPhases.yellow - }, - }, - - [feedbackType.isWarningRed]: { - name: 'Timer is showing red wrap-up warning', - type: 'boolean', - defaultStyle: { - color: colors.red, - }, - options: [], - callback: (_feedback) => { - let { phase } = instance.state.playback_status - return phase == timerPhases.red - }, - }, - - [feedbackType.isFlashing]: { - name: 'Flashing', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return instance.state.viewer.isFlashing - }, - }, - - [feedbackType.blackoutEnabled]: { - name: 'Blackout mode', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return instance.state.room.roomBlackout - }, - }, - - [feedbackType.focusEnabled]: { - name: 'Focus mode', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return instance.state.room.roomFocus - }, - }, - - [feedbackType.messageIsShowing]: { - name: 'Message showing', - type: 'boolean', - defaultStyle: { - bgcolor: colors.red, - color: colors.white, - }, - options: [], - callback: (_feedback) => { - return instance.state.message.showing - }, - }, - } - - return feedbacks + feedbacks = { + + [feedbackType.isRunning]: { + name: 'Playback running', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return instance.state.playback_status.isRunning + }, + }, + + [feedbackType.isStopped]: { + name: 'Playback stopped', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return !instance.state.playback_status.isRunning + }, + }, + + [feedbackType.isOnTime]: { + name: 'Timer is running and on time', + type: 'boolean', + defaultStyle: { + color: colors.green, + }, + options: [], + callback: (_feedback) => { + let { phase, isRunning } = instance.state.playback_status + return phase == timerPhases.default && isRunning + }, + }, + + [feedbackType.isOverTime]: { + name: 'Timer is over time', + type: 'boolean', + defaultStyle: { + color: colors.red, + }, + options: [], + callback: (_feedback) => { + let { phase } = instance.state.playback_status + return phase == timerPhases.negative + }, + }, + + [feedbackType.isWarningYellow]: { + name: 'Timer is showing yellow wrap-up warning', + type: 'boolean', + defaultStyle: { + color: colors.yellow, + }, + options: [], + callback: (_feedback) => { + let { phase } = instance.state.playback_status + return phase == timerPhases.yellow + }, + }, + + [feedbackType.isWarningRed]: { + name: 'Timer is showing red wrap-up warning', + type: 'boolean', + defaultStyle: { + color: colors.red, + }, + options: [], + callback: (_feedback) => { + let { phase } = instance.state.playback_status + return phase == timerPhases.red + }, + }, + + [feedbackType.isFlashing]: { + name: 'Flashing', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return instance.state.viewer.isFlashing + }, + }, + + [feedbackType.blackoutEnabled]: { + name: 'Blackout mode', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return instance.state.room.roomBlackout + }, + }, + + [feedbackType.focusEnabled]: { + name: 'Focus mode', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return instance.state.room.roomFocus + }, + }, + + [feedbackType.messageIsShowing]: { + name: 'Message showing', + type: 'boolean', + defaultStyle: { + bgcolor: colors.red, + color: colors.white, + }, + options: [], + callback: (_feedback) => { + return instance.state.message.showing + }, + }, + } + + return feedbacks } /** @@ -173,8 +173,8 @@ function generateFeedbacks(instance) { */ export function loadFeedbacks(instance) { - instance.setFeedbackDefinitions( - generateFeedbacks(instance) - ) + instance.setFeedbackDefinitions( + generateFeedbacks(instance) + ) } diff --git a/src/index.js b/src/index.js index 70bddab..b8cbb16 100644 --- a/src/index.js +++ b/src/index.js @@ -9,54 +9,54 @@ import { loadVariables } from './variables.js' import { loadPresets } from './presets.js' export class ModuleInstance extends InstanceBase { - constructor(internal) { - super(internal) - } - - config = initialConfig - state = initialState - - async init(config) { - await this.configure(config) - } - - async configUpdated(config) { - await this.configure(config) - } - - async configure(config) { - try { - validateConfig(config) - } catch (error) { - this.updateStatus(InstanceStatus.BadConfig) - this.log('error', error.message) - return - } - - this.config = config - this.apiClient = new ApiClient(config) - - startState(this) - - socketStart(this) - - try { - loadActions(this) - loadFeedbacks(this) - loadVariables(this) - loadPresets(this) - } catch (error) { - throw new Error(`Failed to start. Error: ${error.message}`) - } - } - - getConfigFields() { - return configFields - } - - async destroy() { - socketStop() - } + constructor(internal) { + super(internal) + } + + config = initialConfig + state = initialState + + async init(config) { + await this.configure(config) + } + + async configUpdated(config) { + await this.configure(config) + } + + async configure(config) { + try { + validateConfig(config) + } catch (error) { + this.updateStatus(InstanceStatus.BadConfig) + this.log('error', error.message) + return + } + + this.config = config + this.apiClient = new ApiClient(config) + + startState(this) + + socketStart(this) + + try { + loadActions(this) + loadFeedbacks(this) + loadVariables(this) + loadPresets(this) + } catch (error) { + throw new Error(`Failed to start. Error: ${error.message}`) + } + } + + getConfigFields() { + return configFields + } + + async destroy() { + socketStop() + } } runEntrypoint(ModuleInstance, []) diff --git a/src/presets.js b/src/presets.js index ce81274..3d5cd8a 100644 --- a/src/presets.js +++ b/src/presets.js @@ -14,442 +14,442 @@ let presets = {} */ function generatePresets() { - /** @type {PresetDefinitions} */ - const presets_template = { - 'Transport': [ - // Standard transport buttons - { - name: 'Start/stop toggle', - actionId: actionIdType.start_or_stop, - style: { - size: '14', - text: 'Start/stop', - alignment: 'center:bottom', - png64: icons.play, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.isRunning, { - png64: icons.pause, - }), - ], - }, - { - name: 'Start', - actionId: actionIdType.start, - style: { - size: '14', - text: 'Start', - alignment: 'center:bottom', - png64: icons.play, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.isRunning) - ] - }, - { - name: 'Stop', - actionId: actionIdType.stop, - style: { - size: '14', - text: 'Stop', - alignment: 'center:bottom', - png64: icons.pause, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.isStopped) - ] - }, - { - name: 'Previous', - actionId: actionIdType.previous, - style: { - size: '14', - text: 'Previous', - alignment: 'center:bottom', - png64: icons.previous, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - }, - { - name: 'Next', - actionId: actionIdType.next, - style: { - size: '14', - text: 'Next', - alignment: 'center:bottom', - png64: icons.next, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - }, + /** @type {PresetDefinitions} */ + const presets_template = { + 'Transport': [ + // Standard transport buttons + { + name: 'Start/stop toggle', + actionId: actionIdType.start_or_stop, + style: { + size: '14', + text: 'Start/stop', + alignment: 'center:bottom', + png64: icons.play, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isRunning, { + png64: icons.pause, + }), + ], + }, + { + name: 'Start', + actionId: actionIdType.start, + style: { + size: '14', + text: 'Start', + alignment: 'center:bottom', + png64: icons.play, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isRunning) + ] + }, + { + name: 'Stop', + actionId: actionIdType.stop, + style: { + size: '14', + text: 'Stop', + alignment: 'center:bottom', + png64: icons.pause, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isStopped) + ] + }, + { + name: 'Previous', + actionId: actionIdType.previous, + style: { + size: '14', + text: 'Previous', + alignment: 'center:bottom', + png64: icons.previous, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + }, + { + name: 'Next', + actionId: actionIdType.next, + style: { + size: '14', + text: 'Next', + alignment: 'center:bottom', + png64: icons.next, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + }, - // Variations of add/subtract time - { - name: '+1min', - actionId: actionIdType.add_time, - actionOptions: { - amount: '1m', - }, - style: { - size: '24', - text: '+1min', - alignment: 'center:center', - color: colors.lightGreen, - bgcolor: colors.black, - }, - }, - { - name: '-1m', - actionId: actionIdType.subtract_time, - actionOptions: { - amount: '1m', - }, - style: { - size: '24', - text: '-1m', - alignment: 'center:center', - color: colors.lightRed, - bgcolor: colors.black, - }, - }, - { - name: '+30s', - actionId: actionIdType.add_time, - actionOptions: { - amount: '30s', - }, - style: { - size: '24', - text: '+30s', - alignment: 'center:center', - color: colors.lightGreen, - bgcolor: colors.black, - }, - }, - { - name: '-30s', - actionId: actionIdType.subtract_time, - actionOptions: { - amount: '30s', - }, - style: { - size: '24', - text: '-30s', - alignment: 'center:center', - color: colors.lightRed, - bgcolor: colors.black, - }, - }, - { - name: '+5min', - actionId: actionIdType.add_time, - actionOptions: { - amount: '5m', - }, - style: { - size: '24', - text: '+5min', - alignment: 'center:center', - color: colors.lightGreen, - bgcolor: colors.black, - }, - }, - { - name: '-5m', - actionId: actionIdType.subtract_time, - actionOptions: { - amount: '5m', - }, - style: { - size: '24', - text: '-5m', - alignment: 'center:center', - color: colors.lightRed, - bgcolor: colors.black, - }, - }, - ], + // Variations of add/subtract time + { + name: '+1min', + actionId: actionIdType.add_time, + actionOptions: { + amount: '1m', + }, + style: { + size: '24', + text: '+1min', + alignment: 'center:center', + color: colors.lightGreen, + bgcolor: colors.black, + }, + }, + { + name: '-1m', + actionId: actionIdType.subtract_time, + actionOptions: { + amount: '1m', + }, + style: { + size: '24', + text: '-1m', + alignment: 'center:center', + color: colors.lightRed, + bgcolor: colors.black, + }, + }, + { + name: '+30s', + actionId: actionIdType.add_time, + actionOptions: { + amount: '30s', + }, + style: { + size: '24', + text: '+30s', + alignment: 'center:center', + color: colors.lightGreen, + bgcolor: colors.black, + }, + }, + { + name: '-30s', + actionId: actionIdType.subtract_time, + actionOptions: { + amount: '30s', + }, + style: { + size: '24', + text: '-30s', + alignment: 'center:center', + color: colors.lightRed, + bgcolor: colors.black, + }, + }, + { + name: '+5min', + actionId: actionIdType.add_time, + actionOptions: { + amount: '5m', + }, + style: { + size: '24', + text: '+5min', + alignment: 'center:center', + color: colors.lightGreen, + bgcolor: colors.black, + }, + }, + { + name: '-5m', + actionId: actionIdType.subtract_time, + actionOptions: { + amount: '5m', + }, + style: { + size: '24', + text: '-5m', + alignment: 'center:center', + color: colors.lightRed, + bgcolor: colors.black, + }, + }, + ], - Viewer: [ - { - name: 'Time remaining', - actionId: '', - style: { - size: '18', - text: `$(stagetimer:${variableType.currentTimerRemaining})`, - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.isOnTime), - getFeedbackDefaults(feedbackType.isOverTime), - getFeedbackDefaults(feedbackType.isWarningYellow), - getFeedbackDefaults(feedbackType.isWarningRed), - ], - }, - { - name: 'Timer status', - actionId: '', - style: { - size: '18', - text: `Ready`, - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.isOnTime, { text: 'On time' }), - getFeedbackDefaults(feedbackType.isOverTime, { text: 'Over time!' }), - getFeedbackDefaults(feedbackType.isWarningYellow, { text: 'Wrap up..' }), - getFeedbackDefaults(feedbackType.isWarningRed, { text: 'Wrap up!' }), - ], - }, - { - name: 'Timer name', - actionId: '', - style: { - size: 'auto', - text: `$(stagetimer:${variableType.currentTimerName})`, - color: colors.lightBlue, - bgcolor: colors.black, - }, - }, - { - name: 'Speaker', - actionId: '', - style: { - size: 'auto', - text: `Speaker: $(stagetimer:${variableType.currentTimerSpeaker})`, - color: colors.lightBlue, - bgcolor: colors.black, - }, - }, - { - name: 'Start flashing', - actionId: actionIdType.start_flashing, - actionOptions: { - count: 3, - }, - style: { - size: '14', - text: 'Flash x3', - alignment: 'center:bottom', - png64: icons.flash, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [getFeedbackDefaults(feedbackType.isFlashing)], - }, - { - name: 'Stop flashing', - actionId: actionIdType.stop_flashing, - style: { - size: '14', - text: 'Flash off', - alignment: 'center:bottom', - png64: icons.flashOff, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [getFeedbackDefaults(feedbackType.isFlashing)], - }, - { - name: 'Toggle blackout mode', - actionId: actionIdType.toggle_blackout, - style: { - size: '14', - text: 'Blackout', - alignment: 'center:bottom', - png64: icons.blackout, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.blackoutEnabled, { - png64: icons.blackoutOff, - }), - ], - }, - { - name: 'Toggle focus mode', - actionId: actionIdType.toggle_focus, - style: { - size: '14', - text: 'Focus', - alignment: 'center:bottom', - png64: icons.focus, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.focusEnabled, { - png64: icons.focusOff, - }), - ], - }, - ], + Viewer: [ + { + name: 'Time remaining', + actionId: '', + style: { + size: '18', + text: `$(stagetimer:${variableType.currentTimerRemaining})`, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isOnTime), + getFeedbackDefaults(feedbackType.isOverTime), + getFeedbackDefaults(feedbackType.isWarningYellow), + getFeedbackDefaults(feedbackType.isWarningRed), + ], + }, + { + name: 'Timer status', + actionId: '', + style: { + size: '18', + text: `Ready`, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isOnTime, { text: 'On time' }), + getFeedbackDefaults(feedbackType.isOverTime, { text: 'Over time!' }), + getFeedbackDefaults(feedbackType.isWarningYellow, { text: 'Wrap up..' }), + getFeedbackDefaults(feedbackType.isWarningRed, { text: 'Wrap up!' }), + ], + }, + { + name: 'Timer name', + actionId: '', + style: { + size: 'auto', + text: `$(stagetimer:${variableType.currentTimerName})`, + color: colors.lightBlue, + bgcolor: colors.black, + }, + }, + { + name: 'Speaker', + actionId: '', + style: { + size: 'auto', + text: `Speaker: $(stagetimer:${variableType.currentTimerSpeaker})`, + color: colors.lightBlue, + bgcolor: colors.black, + }, + }, + { + name: 'Start flashing', + actionId: actionIdType.start_flashing, + actionOptions: { + count: 3, + }, + style: { + size: '14', + text: 'Flash x3', + alignment: 'center:bottom', + png64: icons.flash, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [getFeedbackDefaults(feedbackType.isFlashing)], + }, + { + name: 'Stop flashing', + actionId: actionIdType.stop_flashing, + style: { + size: '14', + text: 'Flash off', + alignment: 'center:bottom', + png64: icons.flashOff, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [getFeedbackDefaults(feedbackType.isFlashing)], + }, + { + name: 'Toggle blackout mode', + actionId: actionIdType.toggle_blackout, + style: { + size: '14', + text: 'Blackout', + alignment: 'center:bottom', + png64: icons.blackout, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.blackoutEnabled, { + png64: icons.blackoutOff, + }), + ], + }, + { + name: 'Toggle focus mode', + actionId: actionIdType.toggle_focus, + style: { + size: '14', + text: 'Focus', + alignment: 'center:bottom', + png64: icons.focus, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.focusEnabled, { + png64: icons.focusOff, + }), + ], + }, + ], - Timer: [ - { - name: 'Reset a timer', - actionId: actionIdType.reset_timer, - actionOptions: { - index: 1, - }, - style: { - size: '14', - text: 'Reset', - alignment: 'center:bottom', - png64: icons.timerReset, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [], - }, - { - name: 'Start a timer', - actionId: actionIdType.start_timer, - actionOptions: { - index: 2, - }, - style: { - size: '14', - text: 'Start #2', - alignment: 'center:bottom', - png64: icons.timer, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [], - }, - { - name: 'Stop a timer', - actionId: actionIdType.stop_timer, - actionOptions: { - index: 2, - }, - style: { - size: '14', - text: 'Stop #2', - alignment: 'center:bottom', - png64: icons.timer, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [], - }, - ], + Timer: [ + { + name: 'Reset a timer', + actionId: actionIdType.reset_timer, + actionOptions: { + index: 1, + }, + style: { + size: '14', + text: 'Reset', + alignment: 'center:bottom', + png64: icons.timerReset, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, + { + name: 'Start a timer', + actionId: actionIdType.start_timer, + actionOptions: { + index: 2, + }, + style: { + size: '14', + text: 'Start #2', + alignment: 'center:bottom', + png64: icons.timer, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, + { + name: 'Stop a timer', + actionId: actionIdType.stop_timer, + actionOptions: { + index: 2, + }, + style: { + size: '14', + text: 'Stop #2', + alignment: 'center:bottom', + png64: icons.timer, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, + ], - 'Message': [ - { - name: 'Show/hide message', - actionId: actionIdType.show_or_hide_message, - actionOptions: { - index: 1, - }, - style: { - size: '14', - text: 'Toggle #1', - alignment: 'center:bottom', - png64: icons.message, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [ - getFeedbackDefaults(feedbackType.messageIsShowing, { - png64: icons.messageOff, - }), - ], - }, - { - name: 'Show message', - actionId: actionIdType.show_message, - actionOptions: { - index: 2, - }, - style: { - size: '14', - text: 'Show #2', - alignment: 'center:bottom', - png64: icons.message, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [], - }, - { - name: 'Hide message', - actionId: actionIdType.hide_message, - actionOptions: { - index: 2, - }, - style: { - size: '14', - text: 'Hide #2', - alignment: 'center:bottom', - png64: icons.messageOff, - pngalignment: 'center:top', - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: [], - }, - ], - } + 'Message': [ + { + name: 'Show/hide message', + actionId: actionIdType.show_or_hide_message, + actionOptions: { + index: 1, + }, + style: { + size: '14', + text: 'Toggle #1', + alignment: 'center:bottom', + png64: icons.message, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.messageIsShowing, { + png64: icons.messageOff, + }), + ], + }, + { + name: 'Show message', + actionId: actionIdType.show_message, + actionOptions: { + index: 2, + }, + style: { + size: '14', + text: 'Show #2', + alignment: 'center:bottom', + png64: icons.message, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, + { + name: 'Hide message', + actionId: actionIdType.hide_message, + actionOptions: { + index: 2, + }, + style: { + size: '14', + text: 'Hide #2', + alignment: 'center:bottom', + png64: icons.messageOff, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, + ], + } - for (const [buttonCategory, buttons] of Object.entries(presets_template)) { + for (const [buttonCategory, buttons] of Object.entries(presets_template)) { - for (const button of buttons) { + for (const button of buttons) { - presets[button.name] = { - type: 'button', - category: buttonCategory, - name: button.name, - steps: button.steps || [ - { - down: button.actionId - ? [ - { - actionId: button.actionId, - options: button.actionOptions || {}, - }, - ] - : [], - up: [], - }, - ], - style: button.style || { - size: 'auto', - text: button.name, - color: colors.white, - bgcolor: colors.black, - }, - feedbacks: button.feedbacks || [], - } - } - } + presets[button.name] = { + type: 'button', + category: buttonCategory, + name: button.name, + steps: button.steps || [ + { + down: button.actionId + ? [ + { + actionId: button.actionId, + options: button.actionOptions || {}, + }, + ] + : [], + up: [], + }, + ], + style: button.style || { + size: 'auto', + text: button.name, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: button.feedbacks || [], + } + } + } - return presets + return presets } /** @@ -459,16 +459,16 @@ function generatePresets() { */ export function getFeedbackDefaults(feedbackId, styleOverrides) { - if (feedbacks[feedbackId]) { - return { - feedbackId: feedbackId, - options: {}, - style: { - ...feedbacks[feedbackId]['defaultStyle'], - ...styleOverrides, - }, - } - } + if (feedbacks[feedbackId]) { + return { + feedbackId: feedbackId, + options: {}, + style: { + ...feedbacks[feedbackId]['defaultStyle'], + ...styleOverrides, + }, + } + } } @@ -479,8 +479,8 @@ export function getFeedbackDefaults(feedbackId, styleOverrides) { */ export function loadPresets(instance) { - instance.setPresetDefinitions( - generatePresets() - ) + instance.setPresetDefinitions( + generatePresets() + ) } diff --git a/src/socket.js b/src/socket.js index 23ab096..a0b1b87 100644 --- a/src/socket.js +++ b/src/socket.js @@ -1,11 +1,11 @@ import { InstanceStatus } from '@companion-module/base' import { io } from 'socket.io-client' import { - updatePlaybackState, - updateRoomState, - updateTimerState, - updateFlashingState, - updateMessageState, + updatePlaybackState, + updateRoomState, + updateTimerState, + updateFlashingState, + updateMessageState, } from './state.js' import { actionIdType } from './actions.js' @@ -19,10 +19,10 @@ let socket = null * @enum {string} */ export const stagetimerEvents = { - playback_status: 'playback_status', - room: 'room', - flash: 'flash', - message: 'message', + playback_status: 'playback_status', + room: 'room', + flash: 'flash', + message: 'message', } /** @@ -31,9 +31,9 @@ export const stagetimerEvents = { * @returns {void} */ export function socketStop() { - if (socket) { - socket.disconnect() - } + if (socket) { + socket.disconnect() + } } /** @@ -44,173 +44,173 @@ export function socketStop() { */ export function socketStart(instance) { - if (!instance || !instance.config) { - throw Error('Module instance required') - } - - const { apiUrl, roomId, apiKey } = instance.config - const url = new URL(apiUrl) - - socketStop() - - instance.log('info', 'Connecting to Stagetimer.io...') - instance.updateStatus(InstanceStatus.Connecting) - - // Configure socket - socket = io(url.origin, { - path: url.pathname + 'socket.io', - auth: { - room_id: roomId, - api_key: apiKey, - }, - // Prevent infinite retries - reconnectionAttempts: 5, - // Prevent infinite exponential backoff - reconnectionDelayMax: 10000, - }) - - // - // Socket events - // - - socket.on('connect', () => { - instance.log('info', 'Connected!') - instance.updateStatus(InstanceStatus.Ok) - - instance.apiClient.send(actionIdType.get_room, {}) - .then(({ data }) => { - - const { _id, name, blackout, focus_message } = data - - updateRoomState({ - roomId: _id, - roomName: name, - roomBlackout: blackout, - roomFocus: focus_message, - }) - }) - .catch((error) => { - instance.log('error', error.toString()) - }) - - instance.apiClient.send(actionIdType.get_status, {}) - .then(({ data }) => { - - const { timer_id, running, start, finish, pause } = data - - updatePlaybackState({ - currentTimerId: timer_id, - isRunning: running, - kickoff: start, - deadline: finish, - lastStop: pause, - }) - - return timer_id - }) - .then((timer_id) => { - if (!timer_id) { return false } - getTimerAndUpdateState(instance, timer_id) - }) - .catch((error) => { - instance.log('error', error.toString()) - }) - }) - - socket.on('connect_error', (error) => { - instance.log('warn', `Failed to connect! (${error.message})`) - instance.updateStatus(InstanceStatus.ConnectionFailure) - }) - - socket.on('disconnect', (reason) => { - if (reason === 'io client disconnect') { return } - instance.log('warn', `Disconnected! Reason: ${reason}`) - instance.updateStatus(InstanceStatus.Disconnected) - }) - - socket.on('error', (error) => { - instance.log('error', `Unexpected error: ${error.message}`) - instance.updateStatus(InstanceStatus.UnknownError) - }) - - // - // Socket IO Manager events - // - - socket.io.on('reconnect_attempt', (attempt) => { - instance.log('warn', `Reconnecting... (Attempt #${attempt})`) - instance.updateStatus(InstanceStatus.Connecting) - }) - - socket.io.on('reconnect', (attempt) => { - instance.log('info', `Reconnected on attempt #${attempt}!`) - instance.updateStatus(InstanceStatus.Ok) - }) - - socket.io.on('reconnect_failed', () => { - instance.log('error', `Unable to connect to Stagetimer.io!`) - instance.updateStatus(InstanceStatus.ConnectionFailure) - }) - - socket.io.on('error', (error) => { - instance.log('debug', `[Socket manager] Unexpected error: ${error}`) - }) - - // - // Stagetimer events - // - - socket.on(stagetimerEvents.playback_status, (payload) => { - instance.log('debug', 'Event: playback_status') - - const { timer_id, running, start, finish, pause } = payload - - updatePlaybackState({ - currentTimerId: timer_id, - isRunning: running, - kickoff: start, - deadline: finish, - lastStop: pause, - }) - - getTimerAndUpdateState(instance, timer_id) - }) - - socket.on(stagetimerEvents.room, (payload) => { - instance.log('debug', 'Event: room') - - const { blackout, focus_message } = payload - - updateRoomState({ - roomBlackout: blackout, - roomFocus: focus_message, - }) - }) - - socket.on(stagetimerEvents.message, (payload) => { - instance.log('debug', 'Event: message') - - const { showing, text, color, bold, uppercase } = payload - - updateMessageState({ - showing, - text, - color, - bold, - uppercase, - }) - }) - - socket.on(stagetimerEvents.flash, (payload) => { - instance.log('debug', 'Event: flash') - - const { count } = payload - - updateFlashingState(count) - }) - - // Start - socket.connect() + if (!instance || !instance.config) { + throw Error('Module instance required') + } + + const { apiUrl, roomId, apiKey } = instance.config + const url = new URL(apiUrl) + + socketStop() + + instance.log('info', 'Connecting to Stagetimer.io...') + instance.updateStatus(InstanceStatus.Connecting) + + // Configure socket + socket = io(url.origin, { + path: url.pathname + 'socket.io', + auth: { + room_id: roomId, + api_key: apiKey, + }, + // Prevent infinite retries + reconnectionAttempts: 5, + // Prevent infinite exponential backoff + reconnectionDelayMax: 10000, + }) + + // + // Socket events + // + + socket.on('connect', () => { + instance.log('info', 'Connected!') + instance.updateStatus(InstanceStatus.Ok) + + instance.apiClient.send(actionIdType.get_room, {}) + .then(({ data }) => { + + const { _id, name, blackout, focus_message } = data + + updateRoomState({ + roomId: _id, + roomName: name, + roomBlackout: blackout, + roomFocus: focus_message, + }) + }) + .catch((error) => { + instance.log('error', error.toString()) + }) + + instance.apiClient.send(actionIdType.get_status, {}) + .then(({ data }) => { + + const { timer_id, running, start, finish, pause } = data + + updatePlaybackState({ + currentTimerId: timer_id, + isRunning: running, + kickoff: start, + deadline: finish, + lastStop: pause, + }) + + return timer_id + }) + .then((timer_id) => { + if (!timer_id) { return false } + getTimerAndUpdateState(instance, timer_id) + }) + .catch((error) => { + instance.log('error', error.toString()) + }) + }) + + socket.on('connect_error', (error) => { + instance.log('warn', `Failed to connect! (${error.message})`) + instance.updateStatus(InstanceStatus.ConnectionFailure) + }) + + socket.on('disconnect', (reason) => { + if (reason === 'io client disconnect') { return } + instance.log('warn', `Disconnected! Reason: ${reason}`) + instance.updateStatus(InstanceStatus.Disconnected) + }) + + socket.on('error', (error) => { + instance.log('error', `Unexpected error: ${error.message}`) + instance.updateStatus(InstanceStatus.UnknownError) + }) + + // + // Socket IO Manager events + // + + socket.io.on('reconnect_attempt', (attempt) => { + instance.log('warn', `Reconnecting... (Attempt #${attempt})`) + instance.updateStatus(InstanceStatus.Connecting) + }) + + socket.io.on('reconnect', (attempt) => { + instance.log('info', `Reconnected on attempt #${attempt}!`) + instance.updateStatus(InstanceStatus.Ok) + }) + + socket.io.on('reconnect_failed', () => { + instance.log('error', `Unable to connect to Stagetimer.io!`) + instance.updateStatus(InstanceStatus.ConnectionFailure) + }) + + socket.io.on('error', (error) => { + instance.log('debug', `[Socket manager] Unexpected error: ${error}`) + }) + + // + // Stagetimer events + // + + socket.on(stagetimerEvents.playback_status, (payload) => { + instance.log('debug', 'Event: playback_status') + + const { timer_id, running, start, finish, pause } = payload + + updatePlaybackState({ + currentTimerId: timer_id, + isRunning: running, + kickoff: start, + deadline: finish, + lastStop: pause, + }) + + getTimerAndUpdateState(instance, timer_id) + }) + + socket.on(stagetimerEvents.room, (payload) => { + instance.log('debug', 'Event: room') + + const { blackout, focus_message } = payload + + updateRoomState({ + roomBlackout: blackout, + roomFocus: focus_message, + }) + }) + + socket.on(stagetimerEvents.message, (payload) => { + instance.log('debug', 'Event: message') + + const { showing, text, color, bold, uppercase } = payload + + updateMessageState({ + showing, + text, + color, + bold, + uppercase, + }) + }) + + socket.on(stagetimerEvents.flash, (payload) => { + instance.log('debug', 'Event: flash') + + const { count } = payload + + updateFlashingState(count) + }) + + // Start + socket.connect() } /** @@ -220,21 +220,21 @@ export function socketStart(instance) { */ function getTimerAndUpdateState(instance, timer_id) { - instance.apiClient.send(actionIdType.get_timer, { timer_id }) - .then(({ data }) => { - - const { name, speaker, notes, duration, wrap_up_yellow, wrap_up_red } = data - - updateTimerState({ - name, - speaker, - notes, - duration, - wrap_up_yellow, - wrap_up_red, - }) - }) - .catch((error) => { - instance.log('error', error.toString()) - }) + instance.apiClient.send(actionIdType.get_timer, { timer_id }) + .then(({ data }) => { + + const { name, speaker, notes, duration, wrap_up_yellow, wrap_up_red } = data + + updateTimerState({ + name, + speaker, + notes, + duration, + wrap_up_yellow, + wrap_up_red, + }) + }) + .catch((error) => { + instance.log('error', error.toString()) + }) } diff --git a/src/state.js b/src/state.js index abaa5b2..34bdaba 100644 --- a/src/state.js +++ b/src/state.js @@ -12,7 +12,7 @@ let instance = null * @returns {void} */ export function startState(theInstance) { - instance = theInstance + instance = theInstance } // @@ -21,13 +21,13 @@ export function startState(theInstance) { let timerKeeperId = null function startTimeKeeper() { - if (timerKeeperId !== null) { return } - timerKeeperId = setInterval(updatePlaybackState, 500) + if (timerKeeperId !== null) { return } + timerKeeperId = setInterval(updatePlaybackState, 500) } function stopTimeKeeper() { - clearInterval(timerKeeperId) - timerKeeperId = null + clearInterval(timerKeeperId) + timerKeeperId = null } @@ -38,11 +38,11 @@ function stopTimeKeeper() { * @enum {string} */ export const timerPhases = { - default: 'default', - yellow: 'yellow', - red: 'red', - zero: 'zero', - negative: 'negative', + default: 'default', + yellow: 'yellow', + red: 'red', + zero: 'zero', + negative: 'negative', } /** @@ -54,48 +54,48 @@ export const timerPhases = { * @returns {timerPhases} */ export function getTimerPhase(timeRemaining, yellowTime, redTime) { - if (timeRemaining < 0) return timerPhases.negative - if (timeRemaining <= 0) return timerPhases.zero - if (timeRemaining <= redTime * 1000) return timerPhases.red - if (timeRemaining <= yellowTime * 1000) return timerPhases.yellow - return timerPhases.default + if (timeRemaining < 0) return timerPhases.negative + if (timeRemaining <= 0) return timerPhases.zero + if (timeRemaining <= redTime * 1000) return timerPhases.red + if (timeRemaining <= yellowTime * 1000) return timerPhases.yellow + return timerPhases.default } /** @type {State} */ export const initialState = { - room: { - roomId: null, - roomName: null, - roomBlackout: null, - roomFocus: null, - }, - viewer: { - isFlashing: false, - }, - playback_status: { - currentTimerId: null, - isRunning: null, - kickoff: null, - deadline: null, - lastStop: null, - phase: 'default', - }, - timer: { - name: null, - speaker: null, - notes: null, - duration: null, - wrap_up_yellow: null, - wrap_up_red: null, - }, - message: { - showing: null, - text: null, - color: null, - bold: null, - uppercase: null, - }, + room: { + roomId: null, + roomName: null, + roomBlackout: null, + roomFocus: null, + }, + viewer: { + isFlashing: false, + }, + playback_status: { + currentTimerId: null, + isRunning: null, + kickoff: null, + deadline: null, + lastStop: null, + phase: 'default', + }, + timer: { + name: null, + speaker: null, + notes: null, + duration: null, + wrap_up_yellow: null, + wrap_up_red: null, + }, + message: { + showing: null, + text: null, + color: null, + bold: null, + uppercase: null, + }, } /** @@ -104,22 +104,22 @@ export const initialState = { */ export function updateRoomState(newState) { - const updatedState = { - ...instance.state.room, - ...newState, - } + const updatedState = { + ...instance.state.room, + ...newState, + } - instance.state.room = updatedState + instance.state.room = updatedState - instance.setVariableValues({ - [variableType.roomId]: updatedState.roomId, - [variableType.roomName]: updatedState.roomName, - }) + instance.setVariableValues({ + [variableType.roomId]: updatedState.roomId, + [variableType.roomName]: updatedState.roomName, + }) - instance.checkFeedbacks( - feedbackType.blackoutEnabled, - feedbackType.focusEnabled, - ) + instance.checkFeedbacks( + feedbackType.blackoutEnabled, + feedbackType.focusEnabled, + ) } @@ -129,41 +129,41 @@ export function updateRoomState(newState) { */ export function updatePlaybackState(newState = instance.state.playback_status) { - const updatedState = createTimeset(newState) + const updatedState = createTimeset(newState) - updatedState.phase = getTimerPhase( - updatedState.remaining, - instance.state.timer.wrap_up_yellow, - instance.state.timer.wrap_up_red - ) + updatedState.phase = getTimerPhase( + updatedState.remaining, + instance.state.timer.wrap_up_yellow, + instance.state.timer.wrap_up_red + ) - instance.state.playback_status = updatedState + instance.state.playback_status = updatedState - // Only enable timekeeper polling if timer is active - if (updatedState.isRunning) { - startTimeKeeper() - } else { - stopTimeKeeper() - } + // Only enable timekeeper polling if timer is active + if (updatedState.isRunning) { + startTimeKeeper() + } else { + stopTimeKeeper() + } - instance.setVariableValues({ - [variableType.currentTimerId]: updatedState.currentTimerId, + instance.setVariableValues({ + [variableType.currentTimerId]: updatedState.currentTimerId, - [variableType.currentTimerDuration]: formatDuration(updatedState.total), - [variableType.currentTimerDurationAsMs]: updatedState.total, + [variableType.currentTimerDuration]: formatDuration(updatedState.total), + [variableType.currentTimerDurationAsMs]: updatedState.total, - [variableType.currentTimerRemaining]: formatDuration(updatedState.remaining), - [variableType.currentTimerRemainingAsMs]: updatedState.remaining, - }) + [variableType.currentTimerRemaining]: formatDuration(updatedState.remaining), + [variableType.currentTimerRemainingAsMs]: updatedState.remaining, + }) - instance.checkFeedbacks( - feedbackType.isRunning, - feedbackType.isStopped, - feedbackType.isOnTime, - feedbackType.isOverTime, - feedbackType.isWarningYellow, - feedbackType.isWarningRed - ) + instance.checkFeedbacks( + feedbackType.isRunning, + feedbackType.isStopped, + feedbackType.isOnTime, + feedbackType.isOverTime, + feedbackType.isWarningYellow, + feedbackType.isWarningRed + ) } @@ -173,31 +173,31 @@ export function updatePlaybackState(newState = instance.state.playback_status) { */ export function updateTimerState(newState) { - const updatedState = { - ...instance.state.timer, - ...newState, - } + const updatedState = { + ...instance.state.timer, + ...newState, + } - instance.state.timer = updatedState + instance.state.timer = updatedState - // Update `phase` using `playback_status` and `timer` state - instance.state.playback_status.phase = getTimerPhase( - instance.state.playback_status.remaining, - instance.state.timer.wrap_up_yellow, - instance.state.timer.wrap_up_red - ) + // Update `phase` using `playback_status` and `timer` state + instance.state.playback_status.phase = getTimerPhase( + instance.state.playback_status.remaining, + instance.state.timer.wrap_up_yellow, + instance.state.timer.wrap_up_red + ) - instance.setVariableValues({ - [variableType.currentTimerName]: updatedState.name, - [variableType.currentTimerNotes]: updatedState.notes, - [variableType.currentTimerSpeaker]: updatedState.speaker, - [variableType.currentTimerDuration]: updatedState.duration, - }) + instance.setVariableValues({ + [variableType.currentTimerName]: updatedState.name, + [variableType.currentTimerNotes]: updatedState.notes, + [variableType.currentTimerSpeaker]: updatedState.speaker, + [variableType.currentTimerDuration]: updatedState.duration, + }) - instance.checkFeedbacks( - feedbackType.isWarningYellow, - feedbackType.isWarningRed - ) + instance.checkFeedbacks( + feedbackType.isWarningYellow, + feedbackType.isWarningRed + ) } @@ -207,14 +207,14 @@ export function updateTimerState(newState) { */ export function updateMessageState(newState) { - instance.state.message = { - ...instance.state.message, - ...newState, - } + instance.state.message = { + ...instance.state.message, + ...newState, + } - instance.checkFeedbacks( - feedbackType.messageIsShowing, - ) + instance.checkFeedbacks( + feedbackType.messageIsShowing, + ) } @@ -224,22 +224,22 @@ export function updateMessageState(newState) { */ export function updateFlashingState(count) { - let shouldFlash = false + let shouldFlash = false - if (count > 0) { + if (count > 0) { - shouldFlash = true + shouldFlash = true - setTimeout(() => { - instance.state.viewer.isFlashing = false - instance.checkFeedbacks(feedbackType.isFlashing) - }, count * 1000) - } + setTimeout(() => { + instance.state.viewer.isFlashing = false + instance.checkFeedbacks(feedbackType.isFlashing) + }, count * 1000) + } - instance.state.viewer.isFlashing = shouldFlash + instance.state.viewer.isFlashing = shouldFlash - instance.checkFeedbacks( - feedbackType.isFlashing - ) + instance.checkFeedbacks( + feedbackType.isFlashing + ) } diff --git a/src/utils.js b/src/utils.js index 6f480e0..5c5be9d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,7 +5,7 @@ import { format } from 'date-fns' * @returns {boolean} */ export function isNegative(number) { - return Math.sign(number) == -1 ? true : false + return Math.sign(number) == -1 ? true : false } // @@ -19,7 +19,7 @@ export function isNegative(number) { * @returns {number} */ function floor50(ms) { - return Math.floor(ms / 50) * 50 + return Math.floor(ms / 50) * 50 } /** @@ -28,7 +28,7 @@ function floor50(ms) { * @returns {number} */ function zero() { - return new Date().setHours(0, 0, 0, 0) + return new Date().setHours(0, 0, 0, 0) } /** @@ -39,26 +39,26 @@ function zero() { * @returns {PlaybackState} */ export function createTimeset(timeset, now = Date.now()) { - const tenMin = 60000 - if (now <= 0) now = Date.now() - - // Calculate 'total' (round 10 ms due to inaccuracies) - const total = timeset.deadline ? timeset.deadline - timeset.kickoff : tenMin - - // Calculate time remaining - let remaining - if (!timeset.deadline) remaining = tenMin - else if (timeset.isRunning) remaining = timeset.deadline - now - else remaining = timeset.deadline - timeset.lastStop - - // Correct edge-case where left > total - if (remaining > total) remaining = total - - return { - ...timeset, - total: floor50(total), - remaining: floor50(remaining), - } + const tenMin = 60000 + if (now <= 0) now = Date.now() + + // Calculate 'total' (round 10 ms due to inaccuracies) + const total = timeset.deadline ? timeset.deadline - timeset.kickoff : tenMin + + // Calculate time remaining + let remaining + if (!timeset.deadline) remaining = tenMin + else if (timeset.isRunning) remaining = timeset.deadline - now + else remaining = timeset.deadline - timeset.lastStop + + // Correct edge-case where left > total + if (remaining > total) remaining = total + + return { + ...timeset, + total: floor50(total), + remaining: floor50(remaining), + } } /** @@ -76,37 +76,37 @@ export function createTimeset(timeset, now = Date.now()) { * @returns {string} The formatted duration string. */ export function formatDuration( - milliseconds = 0, - { includeH = true, includeS = true, includeMs = false, includePrefix = true, customFormat = null } = {} + milliseconds = 0, + { includeH = true, includeS = true, includeMs = false, includePrefix = true, customFormat = null } = {} ) { - // Return an empty string if milliseconds is not a number or is NaN - if (typeof milliseconds !== 'number' || isNaN(milliseconds)) return '' + // Return an empty string if milliseconds is not a number or is NaN + if (typeof milliseconds !== 'number' || isNaN(milliseconds)) return '' - const withMs = includeMs - const withSec = includeS || Math.abs(milliseconds) < 3600000 - const withHrs = includeH || Math.abs(milliseconds) >= 3600000 + const withMs = includeMs + const withSec = includeS || Math.abs(milliseconds) < 3600000 + const withHrs = includeH || Math.abs(milliseconds) >= 3600000 - // Determine the prefix of the output string. - const prefix = isNegative(milliseconds) ? '-' : '' + // Determine the prefix of the output string. + const prefix = isNegative(milliseconds) ? '-' : '' - // Determine the format string based on the options. - let formatStr = 'm' - if (withMs) formatStr = 'm:ss.S' - else if (withSec) formatStr = 'm:ss' - if (withHrs) formatStr = 'm' + formatStr + // Determine the format string based on the options. + let formatStr = 'm' + if (withMs) formatStr = 'm:ss.S' + else if (withSec) formatStr = 'm:ss' + if (withHrs) formatStr = 'm' + formatStr - // Format the duration into the output string - let output = format(zero() + Math.abs(milliseconds), customFormat || formatStr) + // Format the duration into the output string + let output = format(zero() + Math.abs(milliseconds), customFormat || formatStr) - // Add hours to the output if necessary - if (withHrs) { - output = Math.floor(Math.abs(milliseconds) / 3600000) + ':' + output - } + // Add hours to the output if necessary + if (withHrs) { + output = Math.floor(Math.abs(milliseconds) / 3600000) + ':' + output + } - // Add optional prefix - if (includePrefix) { - output = prefix + output - } + // Add optional prefix + if (includePrefix) { + output = prefix + output + } - return output + return output } diff --git a/src/variables.js b/src/variables.js index 4731ba6..70f13c7 100644 --- a/src/variables.js +++ b/src/variables.js @@ -5,36 +5,36 @@ * @enum {string} */ export const variableType = { - roomId: 'roomId', - roomName: 'roomName', + roomId: 'roomId', + roomName: 'roomName', - currentTimerId: 'currentTimerId', - currentTimerName: 'currentTimerName', - currentTimerSpeaker: 'currentTimerSpeaker', - currentTimerNotes: 'currentTimerNotes', + currentTimerId: 'currentTimerId', + currentTimerName: 'currentTimerName', + currentTimerSpeaker: 'currentTimerSpeaker', + currentTimerNotes: 'currentTimerNotes', - currentTimerDuration: 'currentTimerDuration', - currentTimerDurationAsMs: 'currentTimerDurationAsMs', + currentTimerDuration: 'currentTimerDuration', + currentTimerDurationAsMs: 'currentTimerDurationAsMs', - currentTimerRemaining: 'currentTimerRemaining', - currentTimerRemainingAsMs: 'currentTimerRemainingAsMs', + currentTimerRemaining: 'currentTimerRemaining', + currentTimerRemainingAsMs: 'currentTimerRemainingAsMs', } /** @type {CompanionVariableDefinition[]} */ const variables = [ - { variableId: variableType.roomId, name: 'Room ID' }, - { variableId: variableType.roomName, name: 'Room name' }, + { variableId: variableType.roomId, name: 'Room ID' }, + { variableId: variableType.roomName, name: 'Room name' }, - { variableId: variableType.currentTimerId, name: 'Timer ID' }, - { variableId: variableType.currentTimerName, name: 'Timer name' }, - { variableId: variableType.currentTimerSpeaker, name: 'Timer speaker' }, - { variableId: variableType.currentTimerNotes, name: 'Timer notes' }, + { variableId: variableType.currentTimerId, name: 'Timer ID' }, + { variableId: variableType.currentTimerName, name: 'Timer name' }, + { variableId: variableType.currentTimerSpeaker, name: 'Timer speaker' }, + { variableId: variableType.currentTimerNotes, name: 'Timer notes' }, - { variableId: variableType.currentTimerDuration, name: 'Timer duration' }, - { variableId: variableType.currentTimerDurationAsMs, name: 'Timer duration (ms)' }, + { variableId: variableType.currentTimerDuration, name: 'Timer duration' }, + { variableId: variableType.currentTimerDurationAsMs, name: 'Timer duration (ms)' }, - { variableId: variableType.currentTimerRemaining, name: 'Timer remaining time' }, - { variableId: variableType.currentTimerRemainingAsMs, name: 'Timer remaining time (ms)' }, + { variableId: variableType.currentTimerRemaining, name: 'Timer remaining time' }, + { variableId: variableType.currentTimerRemainingAsMs, name: 'Timer remaining time (ms)' }, ] /** @@ -42,5 +42,5 @@ const variables = [ * @returns {void} */ export function loadVariables(instance) { - instance.setVariableDefinitions(variables) + instance.setVariableDefinitions(variables) } From d7365525802c6346512b0414e994172548be3b17 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 6 Jul 2023 23:55:01 +0200 Subject: [PATCH 04/18] style: conform to new eslint rules --- src/actions.js | 8 ++++---- src/api.js | 14 +++++++------- src/config.js | 2 +- src/feedbacks.js | 6 +++--- src/index.js | 12 ++++++------ src/presets.js | 18 +++++++++--------- src/socket.js | 8 ++++---- src/state.js | 28 ++++++++++++++-------------- src/utils.js | 17 +++++++++++------ src/variables.js | 2 +- 10 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/actions.js b/src/actions.js index 89ac8b0..4c1dde9 100644 --- a/src/actions.js +++ b/src/actions.js @@ -126,7 +126,7 @@ const actionOptions = { * @param { ModuleInstance } theInstance * @returns {void} */ -export function loadActions(theInstance) { +export function loadActions (theInstance) { instance = theInstance @@ -303,7 +303,7 @@ export function loadActions(theInstance) { * @param {CompanionActionEvent} event * @returns {Promise} */ -const sendActionToApi = async ({ actionId, options }) => { +async function sendActionToApi ({ actionId, options }) { instance.log('debug', `Action: ${actionId}`) @@ -330,10 +330,10 @@ const sendActionToApi = async ({ actionId, options }) => { * @param {CompanionOptionValues} options * @returns {object} */ -function assignTruthyOptionsToParams(options) { +function assignTruthyOptionsToParams (options) { return Object.fromEntries( - Object.entries(options).filter(([_key, value]) => value) + Object.entries(options).filter(([_key, value]) => value), ) } diff --git a/src/api.js b/src/api.js index 853ca49..0999dc6 100644 --- a/src/api.js +++ b/src/api.js @@ -1,6 +1,6 @@ // Custom error class NetworkError extends Error { - get name() { + get name () { return this.constructor.name } } @@ -8,17 +8,17 @@ class NetworkError extends Error { class HttpError extends Error { /** @param {Response} response */ - constructor(response) { + constructor (response) { super(`${response.status} ${response.statusText}`) } - get name() { + get name () { return this.constructor.name } } class ApiError extends Error { - get name() { + get name () { return this.constructor.name } } @@ -34,7 +34,7 @@ export class ApiClient { * * @param {StagetimerConfig} config */ - constructor(config) { + constructor (config) { this.apiUrl = config.apiUrl this.apiKey = config.apiKey this.roomId = config.roomId @@ -48,7 +48,7 @@ export class ApiClient { * @param {object} queryParams * @returns {Promise} */ - async send(path = '', queryParams = {}) { + async send (path = '', queryParams = {}) { try { const params = { @@ -65,7 +65,7 @@ export class ApiClient { const response = await fetch(url, { // Time out before the default Companion IPC action timeout - signal: AbortSignal.timeout(4900) + signal: AbortSignal.timeout(4900), }) if (!response.ok) { diff --git a/src/config.js b/src/config.js index 0b54ab2..01b2993 100644 --- a/src/config.js +++ b/src/config.js @@ -15,7 +15,7 @@ export const initialConfig = { * @returns {boolean} * @throws */ -export function validateConfig(config) { +export function validateConfig (config) { if ( roomIdRegExp.test(config.roomId) diff --git a/src/feedbacks.js b/src/feedbacks.js index 4a79b50..2425671 100644 --- a/src/feedbacks.js +++ b/src/feedbacks.js @@ -29,7 +29,7 @@ export const feedbackType = { * @param { ModuleInstance } instance * @returns {Feedbacks} */ -function generateFeedbacks(instance) { +function generateFeedbacks (instance) { feedbacks = { @@ -171,10 +171,10 @@ function generateFeedbacks(instance) { * @param { ModuleInstance } instance * @returns {void} */ -export function loadFeedbacks(instance) { +export function loadFeedbacks (instance) { instance.setFeedbackDefinitions( - generateFeedbacks(instance) + generateFeedbacks(instance), ) } diff --git a/src/index.js b/src/index.js index b8cbb16..d61eae9 100644 --- a/src/index.js +++ b/src/index.js @@ -9,22 +9,22 @@ import { loadVariables } from './variables.js' import { loadPresets } from './presets.js' export class ModuleInstance extends InstanceBase { - constructor(internal) { + constructor (internal) { super(internal) } config = initialConfig state = initialState - async init(config) { + async init (config) { await this.configure(config) } - async configUpdated(config) { + async configUpdated (config) { await this.configure(config) } - async configure(config) { + async configure (config) { try { validateConfig(config) } catch (error) { @@ -50,11 +50,11 @@ export class ModuleInstance extends InstanceBase { } } - getConfigFields() { + getConfigFields () { return configFields } - async destroy() { + async destroy () { socketStop() } } diff --git a/src/presets.js b/src/presets.js index 3d5cd8a..48877ef 100644 --- a/src/presets.js +++ b/src/presets.js @@ -12,7 +12,7 @@ let presets = {} * * @returns {CompanionPresetDefinitions} */ -function generatePresets() { +function generatePresets () { /** @type {PresetDefinitions} */ const presets_template = { @@ -49,8 +49,8 @@ function generatePresets() { bgcolor: colors.black, }, feedbacks: [ - getFeedbackDefaults(feedbackType.isRunning) - ] + getFeedbackDefaults(feedbackType.isRunning), + ], }, { name: 'Stop', @@ -65,8 +65,8 @@ function generatePresets() { bgcolor: colors.black, }, feedbacks: [ - getFeedbackDefaults(feedbackType.isStopped) - ] + getFeedbackDefaults(feedbackType.isStopped), + ], }, { name: 'Previous', @@ -204,7 +204,7 @@ function generatePresets() { actionId: '', style: { size: '18', - text: `Ready`, + text: 'Ready', color: colors.white, bgcolor: colors.black, }, @@ -457,7 +457,7 @@ function generatePresets() { * @param {CompanionPresetFeedback['style']} [styleOverrides] * @returns {CompanionPresetFeedback} */ -export function getFeedbackDefaults(feedbackId, styleOverrides) { +export function getFeedbackDefaults (feedbackId, styleOverrides) { if (feedbacks[feedbackId]) { return { @@ -477,10 +477,10 @@ export function getFeedbackDefaults(feedbackId, styleOverrides) { * @param { ModuleInstance } instance * @returns {void} */ -export function loadPresets(instance) { +export function loadPresets (instance) { instance.setPresetDefinitions( - generatePresets() + generatePresets(), ) } diff --git a/src/socket.js b/src/socket.js index a0b1b87..9812de4 100644 --- a/src/socket.js +++ b/src/socket.js @@ -30,7 +30,7 @@ export const stagetimerEvents = { * * @returns {void} */ -export function socketStop() { +export function socketStop () { if (socket) { socket.disconnect() } @@ -42,7 +42,7 @@ export function socketStop() { * @param {ModuleInstance} instance * @returns {void} */ -export function socketStart(instance) { +export function socketStart (instance) { if (!instance || !instance.config) { throw Error('Module instance required') @@ -148,7 +148,7 @@ export function socketStart(instance) { }) socket.io.on('reconnect_failed', () => { - instance.log('error', `Unable to connect to Stagetimer.io!`) + instance.log('error', 'Unable to connect to Stagetimer.io!') instance.updateStatus(InstanceStatus.ConnectionFailure) }) @@ -218,7 +218,7 @@ export function socketStart(instance) { * @param {ModuleInstance} instance * @param {string} timer_id */ -function getTimerAndUpdateState(instance, timer_id) { +function getTimerAndUpdateState (instance, timer_id) { instance.apiClient.send(actionIdType.get_timer, { timer_id }) .then(({ data }) => { diff --git a/src/state.js b/src/state.js index 34bdaba..aa7368b 100644 --- a/src/state.js +++ b/src/state.js @@ -11,7 +11,7 @@ let instance = null * @param {ModuleInstance} theInstance * @returns {void} */ -export function startState(theInstance) { +export function startState (theInstance) { instance = theInstance } @@ -20,12 +20,12 @@ export function startState(theInstance) { // let timerKeeperId = null -function startTimeKeeper() { +function startTimeKeeper () { if (timerKeeperId !== null) { return } timerKeeperId = setInterval(updatePlaybackState, 500) } -function stopTimeKeeper() { +function stopTimeKeeper () { clearInterval(timerKeeperId) timerKeeperId = null } @@ -53,7 +53,7 @@ export const timerPhases = { * @param {number} [redTime] * @returns {timerPhases} */ -export function getTimerPhase(timeRemaining, yellowTime, redTime) { +export function getTimerPhase (timeRemaining, yellowTime, redTime) { if (timeRemaining < 0) return timerPhases.negative if (timeRemaining <= 0) return timerPhases.zero if (timeRemaining <= redTime * 1000) return timerPhases.red @@ -102,7 +102,7 @@ export const initialState = { * @param { RoomState } newState * @returns {void} */ -export function updateRoomState(newState) { +export function updateRoomState (newState) { const updatedState = { ...instance.state.room, @@ -127,14 +127,14 @@ export function updateRoomState(newState) { * @param { PlaybackState } [newState] * @returns {void} */ -export function updatePlaybackState(newState = instance.state.playback_status) { +export function updatePlaybackState (newState = instance.state.playback_status) { const updatedState = createTimeset(newState) updatedState.phase = getTimerPhase( updatedState.remaining, instance.state.timer.wrap_up_yellow, - instance.state.timer.wrap_up_red + instance.state.timer.wrap_up_red, ) instance.state.playback_status = updatedState @@ -162,7 +162,7 @@ export function updatePlaybackState(newState = instance.state.playback_status) { feedbackType.isOnTime, feedbackType.isOverTime, feedbackType.isWarningYellow, - feedbackType.isWarningRed + feedbackType.isWarningRed, ) } @@ -171,7 +171,7 @@ export function updatePlaybackState(newState = instance.state.playback_status) { * @param { TimerState } newState * @returns {void} */ -export function updateTimerState(newState) { +export function updateTimerState (newState) { const updatedState = { ...instance.state.timer, @@ -184,7 +184,7 @@ export function updateTimerState(newState) { instance.state.playback_status.phase = getTimerPhase( instance.state.playback_status.remaining, instance.state.timer.wrap_up_yellow, - instance.state.timer.wrap_up_red + instance.state.timer.wrap_up_red, ) instance.setVariableValues({ @@ -196,7 +196,7 @@ export function updateTimerState(newState) { instance.checkFeedbacks( feedbackType.isWarningYellow, - feedbackType.isWarningRed + feedbackType.isWarningRed, ) } @@ -205,7 +205,7 @@ export function updateTimerState(newState) { * @param { MessageState } newState * @returns {void} */ -export function updateMessageState(newState) { +export function updateMessageState (newState) { instance.state.message = { ...instance.state.message, @@ -222,7 +222,7 @@ export function updateMessageState(newState) { * @param {number} count * @returns {void} */ -export function updateFlashingState(count) { +export function updateFlashingState (count) { let shouldFlash = false @@ -239,7 +239,7 @@ export function updateFlashingState(count) { instance.state.viewer.isFlashing = shouldFlash instance.checkFeedbacks( - feedbackType.isFlashing + feedbackType.isFlashing, ) } diff --git a/src/utils.js b/src/utils.js index 5c5be9d..2ee7abc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -4,7 +4,7 @@ import { format } from 'date-fns' * @param {number} number * @returns {boolean} */ -export function isNegative(number) { +export function isNegative (number) { return Math.sign(number) == -1 ? true : false } @@ -18,7 +18,7 @@ export function isNegative(number) { * @param {number} ms Duration of time as milliseconds. * @returns {number} */ -function floor50(ms) { +function floor50 (ms) { return Math.floor(ms / 50) * 50 } @@ -27,7 +27,7 @@ function floor50(ms) { * * @returns {number} */ -function zero() { +function zero () { return new Date().setHours(0, 0, 0, 0) } @@ -38,7 +38,7 @@ function zero() { * @param {number} now Date in ms * @returns {PlaybackState} */ -export function createTimeset(timeset, now = Date.now()) { +export function createTimeset (timeset, now = Date.now()) { const tenMin = 60000 if (now <= 0) now = Date.now() @@ -75,9 +75,14 @@ export function createTimeset(timeset, now = Date.now()) { * * @returns {string} The formatted duration string. */ -export function formatDuration( +export function formatDuration ( milliseconds = 0, - { includeH = true, includeS = true, includeMs = false, includePrefix = true, customFormat = null } = {} + { includeH = true, + includeS = true, + includeMs = false, + includePrefix = true, + customFormat = null, + } = {}, ) { // Return an empty string if milliseconds is not a number or is NaN if (typeof milliseconds !== 'number' || isNaN(milliseconds)) return '' diff --git a/src/variables.js b/src/variables.js index 70f13c7..d5696f8 100644 --- a/src/variables.js +++ b/src/variables.js @@ -41,6 +41,6 @@ const variables = [ * @param { ModuleInstance } instance * @returns {void} */ -export function loadVariables(instance) { +export function loadVariables (instance) { instance.setVariableDefinitions(variables) } From 441f6b615bfbfa1b28da0295d0a1326aef382b91 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Sat, 8 Jul 2023 22:32:20 +0200 Subject: [PATCH 05/18] =?UTF-8?q?refactor:=20enable=20=E2=80=9Cstrict?= =?UTF-8?q?=E2=80=9D=20type=20checking=20and=20fix=20all=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jsconfig.json | 1 + src/actions.js | 72 ++++++++++++++++++---------------- src/api.js | 1 + src/index.js | 37 ++++++++++++------ src/presets.js | 2 +- src/socket.js | 43 ++++++++++++-------- src/state.js | 104 ++++++++++++++++++++++++++++--------------------- src/types.js | 62 ++++++++++++++++++++++++++--- src/utils.js | 3 +- 9 files changed, 211 insertions(+), 114 deletions(-) diff --git a/jsconfig.json b/jsconfig.json index 99abdb2..0d5f932 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "checkJs": true, + "strict": true, }, "exclude": [ "node_modules", diff --git a/src/actions.js b/src/actions.js index 4c1dde9..5049dff 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,6 +1,3 @@ -/** @type {ModuleInstance} */ -let instance = null - /** * Enum of Action IDs allowed by Stagetimer.io API (v1) * @@ -123,12 +120,12 @@ const actionOptions = { /** - * @param { ModuleInstance } theInstance + * @param { ModuleInstance } instance * @returns {void} */ -export function loadActions (theInstance) { +export function loadActions (instance) { - instance = theInstance + const actionCallback = sendActionToApi.bind(instance) /** @type {CompanionActionDefinitions} */ const all_actions = { @@ -138,43 +135,43 @@ export function loadActions (theInstance) { name: 'Transport: Start', description: 'Start or resume the highlighted timer in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.stop]: { name: 'Transport: Stop', description: 'Stop the highlighted timer in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.start_or_stop]: { name: 'Transport: Start/stop', description: 'Start/stop the highlighted timer in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.next]: { name: 'Transport: Next', description: 'Highlight the next timer in the list', options: actionOptions.autostart, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.previous]: { name: 'Transport: Previous', description: 'Reset the highlighted timer in the room if it is running. If the highlighted timer is not running, highlight the previous timer in the list. Optionally, you can automatically start the previous timer once it\'s highlighted.', options: actionOptions.autostart, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.add_time]: { name: 'Transport: Add time', description: 'Add an amount of time to the highlighted timer in the room.', options: actionOptions.amount, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.subtract_time]: { name: 'Transport: Subtract time', description: 'Subtract an amount of time from the highlighted timer in the room.', options: actionOptions.amount, - callback: sendActionToApi, + callback: actionCallback, }, // Viewer actions @@ -182,49 +179,49 @@ export function loadActions (theInstance) { name: 'Viewer: Flash the screen', description: 'Flashes the screen in the room. Can be used to grab the attention of speakers.', options: actionOptions.count, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.stop_flashing]: { name: 'Viewer: Stop flashing', description: 'Stops any flashing timers and message on the screen.', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.enable_blackout]: { name: 'Viewer: Enable blackout mode', description: 'Enable blackout mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.disable_blackout]: { name: 'Viewer: Disable blackout mode', description: 'Disable blackout mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.toggle_blackout]: { name: 'Viewer: Toggle blackout mode', description: 'Toggle (enable/disable) blackout mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.enable_focus]: { name: 'Viewer: Enable focus mode', description: 'Enable focus mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.disable_focus]: { name: 'Viewer: Disable focus mode', description: 'Disable focus mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.toggle_focus]: { name: 'Viewer: Toggle focus mode', description: 'Toggle (enable/disable) focus mode in the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, // Timer actions @@ -232,25 +229,25 @@ export function loadActions (theInstance) { name: 'Timer: Start', description: 'Start or resume a specific timer in the room', options: actionOptions.timer, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.stop_timer]: { name: 'Timer: Stop', description: 'Stop a specific timer in the room', options: actionOptions.timer, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.start_or_stop_timer]: { name: 'Timer: Toggle playback', description: 'Toggle (start/stop) a specific timer in the room', options: actionOptions.timer, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.reset_timer]: { name: 'Timer: Reset', description: 'Reset a specific timer to original duration', options: actionOptions.timer, - callback: sendActionToApi, + callback: actionCallback, }, // Message actions @@ -258,19 +255,19 @@ export function loadActions (theInstance) { name: 'Message: Show', description: 'Show a message in the room', options: actionOptions.message, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.hide_message]: { name: 'Message: Hide', description: 'Hide a message in the room', options: actionOptions.message, - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.show_or_hide_message]: { name: 'Message: Toggle visibility', description: 'Show/hide a message in the room', options: actionOptions.message, - callback: sendActionToApi, + callback: actionCallback, }, // Developer and utility actions @@ -278,19 +275,19 @@ export function loadActions (theInstance) { name: 'Utility: Test auth', description: 'Test connection and authentication', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.get_status]: { name: 'Utility: Get status', description: 'Get playback status of the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, [actionIdType.get_room]: { name: 'Utility: Get room', description: 'Get status of the room', options: [], - callback: sendActionToApi, + callback: actionCallback, }, } @@ -298,13 +295,16 @@ export function loadActions (theInstance) { } /** - * Handles Action event callbacks and calls the API client + * Handles callbacks from Actions and calls the API client * + * @this {ModuleInstance} * @param {CompanionActionEvent} event * @returns {Promise} */ async function sendActionToApi ({ actionId, options }) { + const instance = this + instance.log('debug', `Action: ${actionId}`) if (actionId in actionIdType === false) { @@ -312,13 +312,19 @@ async function sendActionToApi ({ actionId, options }) { throw new Error('Not a valid actionId') } + if (!instance.apiClient) { + throw new Error('API client not ready') + } + const params = assignTruthyOptionsToParams(options) try { const { message } = await instance.apiClient.send(actionId, params) instance.log('debug', `API response: ${message}`) + } catch (error) { + if (!(error instanceof Error)) { throw new Error } instance.log('error', error.toString()) } } @@ -331,9 +337,7 @@ async function sendActionToApi ({ actionId, options }) { * @returns {object} */ function assignTruthyOptionsToParams (options) { - return Object.fromEntries( Object.entries(options).filter(([_key, value]) => value), ) - } diff --git a/src/api.js b/src/api.js index 0999dc6..69c78f7 100644 --- a/src/api.js +++ b/src/api.js @@ -81,6 +81,7 @@ export class ApiClient { return await response.json() } catch (error) { + if (!(error instanceof Error)) { throw new Error } switch (error.name) { // Handle the timeout with a friendly message case 'TimeoutError': diff --git a/src/index.js b/src/index.js index d61eae9..d85fefb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ import { InstanceBase, runEntrypoint, InstanceStatus } from '@companion-module/base' import { initialConfig, validateConfig, configFields } from './config.js' -import { initialState, startState } from './state.js' +import { initialState } from './state.js' import { ApiClient } from './api.js' import { socketStart, socketStop } from './socket.js' import { loadActions } from './actions.js' @@ -8,45 +8,60 @@ import { loadFeedbacks } from './feedbacks.js' import { loadVariables } from './variables.js' import { loadPresets } from './presets.js' +/** + * @extends {InstanceBase} + */ export class ModuleInstance extends InstanceBase { - constructor (internal) { - super(internal) - } config = initialConfig state = initialState + /** @type {ApiClient | null} */ + apiClient = null + + /** + * @param {StagetimerConfig} config + * @returns {Promise} + */ async init (config) { await this.configure(config) } + /** + * @param {StagetimerConfig} config + * @returns {Promise} + */ async configUpdated (config) { await this.configure(config) } + /** + * @param {StagetimerConfig} config + * @returns {Promise} + */ async configure (config) { try { validateConfig(config) } catch (error) { this.updateStatus(InstanceStatus.BadConfig) - this.log('error', error.message) - return + if(error instanceof Error) { + this.log('error', error.message) + } } this.config = config this.apiClient = new ApiClient(config) - startState(this) - - socketStart(this) - try { + socketStart(this) loadActions(this) loadFeedbacks(this) loadVariables(this) loadPresets(this) } catch (error) { - throw new Error(`Failed to start. Error: ${error.message}`) + if(error instanceof Error) { + throw new Error(`Failed to start. Error: ${error.message}`) + } } } diff --git a/src/presets.js b/src/presets.js index 48877ef..0f5815d 100644 --- a/src/presets.js +++ b/src/presets.js @@ -455,7 +455,7 @@ function generatePresets () { /** * @param {feedbackType} feedbackId * @param {CompanionPresetFeedback['style']} [styleOverrides] - * @returns {CompanionPresetFeedback} + * @returns {CompanionPresetFeedback | undefined} */ export function getFeedbackDefaults (feedbackId, styleOverrides) { diff --git a/src/socket.js b/src/socket.js index 9812de4..f359f72 100644 --- a/src/socket.js +++ b/src/socket.js @@ -9,7 +9,7 @@ import { } from './state.js' import { actionIdType } from './actions.js' -/** @type {import('socket.io-client').Socket} */ +/** @type {Socket | null} */ let socket = null /** @@ -41,6 +41,7 @@ export function socketStop () { * * @param {ModuleInstance} instance * @returns {void} + * @throws */ export function socketStart (instance) { @@ -77,12 +78,16 @@ export function socketStart (instance) { instance.log('info', 'Connected!') instance.updateStatus(InstanceStatus.Ok) + if (!instance.apiClient) { + throw Error('API client not ready') + } + instance.apiClient.send(actionIdType.get_room, {}) .then(({ data }) => { - const { _id, name, blackout, focus_message } = data + const { _id, name, blackout, focus_message } = /** @type {RoomData} */(data) - updateRoomState({ + updateRoomState.call(instance, { roomId: _id, roomName: name, roomBlackout: blackout, @@ -96,9 +101,9 @@ export function socketStart (instance) { instance.apiClient.send(actionIdType.get_status, {}) .then(({ data }) => { - const { timer_id, running, start, finish, pause } = data + const { timer_id, running, start, finish, pause } = /** @type {StatusData} */(data) - updatePlaybackState({ + updatePlaybackState.call(instance, { currentTimerId: timer_id, isRunning: running, kickoff: start, @@ -109,8 +114,7 @@ export function socketStart (instance) { return timer_id }) .then((timer_id) => { - if (!timer_id) { return false } - getTimerAndUpdateState(instance, timer_id) + getTimerAndUpdateState.call(instance, timer_id) }) .catch((error) => { instance.log('error', error.toString()) @@ -165,7 +169,7 @@ export function socketStart (instance) { const { timer_id, running, start, finish, pause } = payload - updatePlaybackState({ + updatePlaybackState.call(instance, { currentTimerId: timer_id, isRunning: running, kickoff: start, @@ -173,7 +177,7 @@ export function socketStart (instance) { lastStop: pause, }) - getTimerAndUpdateState(instance, timer_id) + getTimerAndUpdateState.call(instance, timer_id) }) socket.on(stagetimerEvents.room, (payload) => { @@ -181,7 +185,7 @@ export function socketStart (instance) { const { blackout, focus_message } = payload - updateRoomState({ + updateRoomState.call(instance, { roomBlackout: blackout, roomFocus: focus_message, }) @@ -192,7 +196,7 @@ export function socketStart (instance) { const { showing, text, color, bold, uppercase } = payload - updateMessageState({ + updateMessageState.call(instance, { showing, text, color, @@ -206,7 +210,7 @@ export function socketStart (instance) { const { count } = payload - updateFlashingState(count) + updateFlashingState.call(instance, count) }) // Start @@ -215,17 +219,24 @@ export function socketStart (instance) { /** * - * @param {ModuleInstance} instance * @param {string} timer_id + * @this {ModuleInstance} + * @throws */ -function getTimerAndUpdateState (instance, timer_id) { +function getTimerAndUpdateState (timer_id) { + + const instance = this + + if (!instance.apiClient) { + throw Error('API client not ready') + } instance.apiClient.send(actionIdType.get_timer, { timer_id }) .then(({ data }) => { - const { name, speaker, notes, duration, wrap_up_yellow, wrap_up_red } = data + const { name, speaker, notes, duration, wrap_up_yellow, wrap_up_red } = /** @type {TimerData} */ (data) - updateTimerState({ + updateTimerState.call(this, { name, speaker, notes, diff --git a/src/state.js b/src/state.js index aa7368b..9ea5270 100644 --- a/src/state.js +++ b/src/state.js @@ -2,31 +2,32 @@ import { feedbackType } from './feedbacks.js' import { formatDuration, createTimeset } from './utils.js' import { variableType } from './variables.js' -/** @type {ModuleInstance} */ -let instance = null - -/** - * Start state module - * - * @param {ModuleInstance} theInstance - * @returns {void} - */ -export function startState (theInstance) { - instance = theInstance -} - // // Timekeeper service // +/** @type {NodeJS.Timer | null} */ let timerKeeperId = null +/** + * Start time keeping service + * + * @this {ModuleInstance} + * @returns {void} + */ function startTimeKeeper () { if (timerKeeperId !== null) { return } - timerKeeperId = setInterval(updatePlaybackState, 500) + timerKeeperId = setInterval(updatePlaybackState.bind(this), 500) } +/** + * Stop time keeping serviec + * + * @returns {void} + */ function stopTimeKeeper () { - clearInterval(timerKeeperId) + if(timerKeeperId !== null ) { + clearInterval(timerKeeperId) + } timerKeeperId = null } @@ -53,7 +54,7 @@ export const timerPhases = { * @param {number} [redTime] * @returns {timerPhases} */ -export function getTimerPhase (timeRemaining, yellowTime, redTime) { +export function getTimerPhase (timeRemaining, yellowTime = 0, redTime = 0) { if (timeRemaining < 0) return timerPhases.negative if (timeRemaining <= 0) return timerPhases.zero if (timeRemaining <= redTime * 1000) return timerPhases.red @@ -65,45 +66,48 @@ export function getTimerPhase (timeRemaining, yellowTime, redTime) { /** @type {State} */ export const initialState = { room: { - roomId: null, - roomName: null, - roomBlackout: null, - roomFocus: null, + roomId: undefined, + roomName: undefined, + roomBlackout: false, + roomFocus: false, }, viewer: { isFlashing: false, }, playback_status: { - currentTimerId: null, - isRunning: null, - kickoff: null, - deadline: null, - lastStop: null, - phase: 'default', + currentTimerId: '', + isRunning: false, + kickoff: 0, + deadline: 0, + lastStop: 0, + phase: undefined, }, timer: { - name: null, - speaker: null, - notes: null, - duration: null, - wrap_up_yellow: null, - wrap_up_red: null, + name: '', + speaker: '', + notes: '', + duration: '', + wrap_up_yellow: 0, + wrap_up_red: 0, }, message: { - showing: null, - text: null, - color: null, - bold: null, - uppercase: null, + showing: false, + text: '', + color: '', + bold: false, + uppercase: false, }, } /** * @param { RoomState } newState + * @this {ModuleInstance} * @returns {void} */ export function updateRoomState (newState) { + const instance = this + const updatedState = { ...instance.state.room, ...newState, @@ -125,14 +129,17 @@ export function updateRoomState (newState) { /** * @param { PlaybackState } [newState] + * @this {ModuleInstance} * @returns {void} */ -export function updatePlaybackState (newState = instance.state.playback_status) { +export function updatePlaybackState (newState) { + + const instance = this - const updatedState = createTimeset(newState) + const updatedState = createTimeset(newState || instance.state.playback_status) updatedState.phase = getTimerPhase( - updatedState.remaining, + updatedState.remaining ?? 0, instance.state.timer.wrap_up_yellow, instance.state.timer.wrap_up_red, ) @@ -141,13 +148,13 @@ export function updatePlaybackState (newState = instance.state.playback_status) // Only enable timekeeper polling if timer is active if (updatedState.isRunning) { - startTimeKeeper() + startTimeKeeper.call(this) } else { - stopTimeKeeper() + stopTimeKeeper.call(this) } instance.setVariableValues({ - [variableType.currentTimerId]: updatedState.currentTimerId, + [variableType.currentTimerId]: updatedState.currentTimerId ?? undefined, [variableType.currentTimerDuration]: formatDuration(updatedState.total), [variableType.currentTimerDurationAsMs]: updatedState.total, @@ -169,10 +176,13 @@ export function updatePlaybackState (newState = instance.state.playback_status) /** * @param { TimerState } newState + * @this {ModuleInstance} * @returns {void} */ export function updateTimerState (newState) { + const instance = this + const updatedState = { ...instance.state.timer, ...newState, @@ -182,7 +192,7 @@ export function updateTimerState (newState) { // Update `phase` using `playback_status` and `timer` state instance.state.playback_status.phase = getTimerPhase( - instance.state.playback_status.remaining, + instance.state.playback_status.remaining ?? 0, instance.state.timer.wrap_up_yellow, instance.state.timer.wrap_up_red, ) @@ -203,10 +213,13 @@ export function updateTimerState (newState) { /** * @param { MessageState } newState + * @this {ModuleInstance} * @returns {void} */ export function updateMessageState (newState) { + const instance = this + instance.state.message = { ...instance.state.message, ...newState, @@ -220,10 +233,13 @@ export function updateMessageState (newState) { /** * @param {number} count + * @this {ModuleInstance} * @returns {void} */ export function updateFlashingState (count) { + const instance = this + let shouldFlash = false if (count > 0) { diff --git a/src/types.js b/src/types.js index 583e219..54a135d 100644 --- a/src/types.js +++ b/src/types.js @@ -20,32 +20,82 @@ /** @typedef {import('@companion-module/base').CompanionFeedbackDefinitions} CompanionFeedbackDefinitions */ /** @typedef {import('@companion-module/base').CompanionBooleanFeedbackDefinition} CompanionBooleanFeedbackDefinition */ +/** @typedef {Object} Feedbacks */ +/** @typedef {Object} PresetFeedbacks */ + +// +// External type aliases +// +/** @typedef {import('socket.io-client').Socket} Socket */ + // // Module types // +/** @typedef {import('./index.js').ModuleInstance} ModuleInstance */ + /** + * Module configuration + * * @typedef { object } StagetimerConfig * @property { string } roomId * @property { string } apiKey * @property { string } apiUrl */ -/** @typedef {import('./index.js').ModuleInstance} ModuleInstance */ - -/** @typedef {Object} Feedbacks */ -/** @typedef {Object} PresetFeedbacks */ - /** * Stagetimer.io API response type * * @typedef {object} ApiResponse * @property {boolean} ok * @property {string} message - * @property { Object | Array } [data] + * @property { RoomData | StatusData | TimerData | Array } [data] + */ + +/** + * API response for a Status + * + * @typedef {object} StatusData + * @property {'playback_status'} _model + * @property {Date} _updated_at + * @property {string} timer_id + * @property {boolean} running + * @property {number} start + * @property {number} finish + * @property {number} pause */ /** + * API response for a Room + * + * @typedef {object} RoomData + * @property {string} _id + * @property {'room'} _model + * @property {Date} _updated_at + * @property {string} name + * @property {boolean} blackout + * @property {boolean} focus_message + * @property {string} logo + */ + +/** + * API response for a Timer + * + * @typedef {object} TimerData + * @property {string} _id + * @property {'timer'} _model + * @property {Date} _updated_at + * @property {string} name + * @property {string} speaker + * @property {string} notes + * @property {string} duration + * @property {number} wrap_up_yellow + * @property {number} wrap_up_red + */ + +/** + * Module state object + * * @typedef {object} State * @property {RoomState} room * @property {ViewerState} viewer diff --git a/src/utils.js b/src/utils.js index 2ee7abc..0b9e33c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -81,7 +81,6 @@ export function formatDuration ( includeS = true, includeMs = false, includePrefix = true, - customFormat = null, } = {}, ) { // Return an empty string if milliseconds is not a number or is NaN @@ -101,7 +100,7 @@ export function formatDuration ( if (withHrs) formatStr = 'm' + formatStr // Format the duration into the output string - let output = format(zero() + Math.abs(milliseconds), customFormat || formatStr) + let output = format(zero() + Math.abs(milliseconds), formatStr) // Add hours to the output if necessary if (withHrs) { From ed2aa8354f85e9138e0359e2c0c1b17f9c13bfb1 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:50:58 +0100 Subject: [PATCH 06/18] feat: API no longer requires id or index for Message actions, remove defaults and update presets --- src/actions.js | 15 ++++++--------- src/presets.js | 36 ++++++++++++++---------------------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/actions.js b/src/actions.js index 5049dff..8e43afb 100644 --- a/src/actions.js +++ b/src/actions.js @@ -42,10 +42,6 @@ export const actionIdType = { hide_message: 'hide_message', } -// Reusable labels -let idTip = 'Unique identifier for a ' -let indexTip = 'Index of a timer or message to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second timer from the top, set `index=2`' - /** * Dictionary of Action Input Fields ({@link SomeCompanionActionInputField}) * @@ -90,13 +86,13 @@ const actionOptions = { default: 1, min: 1, max: 99, - tooltip: indexTip, + tooltip: 'Index of a timer to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second timer from the top, set `index=2`', }, { id: 'timer_id', type: 'textinput', label: 'Timer ID', - tooltip: idTip + 'timer', + tooltip: 'The ID of the timer you want to target', }, ], message: [ @@ -104,16 +100,17 @@ const actionOptions = { id: 'index', type: 'number', label: 'Message index', - default: 1, + default: 0, // According to Companion docs, `default: ""` should work for optional, but is of course a type error. 0 seems to work the same but without errors. + required: false, min: 1, max: 99, - tooltip: indexTip, + tooltip: 'Index of a message to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second message from the top, set `index=2`. To target the active/first message, clear the input field.', }, { id: 'message_id', type: 'textinput', label: 'Message ID', - tooltip: idTip + 'message', + tooltip: 'The ID of the message you want to target', }, ], } diff --git a/src/presets.js b/src/presets.js index 0f5815d..9f5d953 100644 --- a/src/presets.js +++ b/src/presets.js @@ -362,12 +362,10 @@ function generatePresets () { { name: 'Show/hide message', actionId: actionIdType.show_or_hide_message, - actionOptions: { - index: 1, - }, + actionOptions: {}, style: { size: '14', - text: 'Toggle #1', + text: 'Toggle', alignment: 'center:bottom', png64: icons.message, pngalignment: 'center:top', @@ -383,12 +381,10 @@ function generatePresets () { { name: 'Show message', actionId: actionIdType.show_message, - actionOptions: { - index: 2, - }, + actionOptions: {}, style: { size: '14', - text: 'Show #2', + text: 'Show', alignment: 'center:bottom', png64: icons.message, pngalignment: 'center:top', @@ -400,12 +396,10 @@ function generatePresets () { { name: 'Hide message', actionId: actionIdType.hide_message, - actionOptions: { - index: 2, - }, + actionOptions: {}, style: { size: '14', - text: 'Hide #2', + text: 'Hide', alignment: 'center:bottom', png64: icons.messageOff, pngalignment: 'center:top', @@ -455,19 +449,17 @@ function generatePresets () { /** * @param {feedbackType} feedbackId * @param {CompanionPresetFeedback['style']} [styleOverrides] - * @returns {CompanionPresetFeedback | undefined} + * @returns {CompanionPresetFeedback} */ export function getFeedbackDefaults (feedbackId, styleOverrides) { - if (feedbacks[feedbackId]) { - return { - feedbackId: feedbackId, - options: {}, - style: { - ...feedbacks[feedbackId]['defaultStyle'], - ...styleOverrides, - }, - } + return { + feedbackId: feedbackId, + options: {}, + style: { + ...feedbacks[feedbackId]['defaultStyle'], + ...styleOverrides, + }, } } From 16a0f1aa74904cf6464ba25aef1a22dde73807dc Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Fri, 10 Nov 2023 16:46:35 +0100 Subject: [PATCH 07/18] feat: add Create Message action and preset --- src/actions.js | 47 ++++++++++++++++++++++++++++++++++++++++++++--- src/assets.js | 1 + src/presets.js | 18 ++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/actions.js b/src/actions.js index 8e43afb..c012fbb 100644 --- a/src/actions.js +++ b/src/actions.js @@ -40,6 +40,7 @@ export const actionIdType = { show_or_hide_message: 'show_or_hide_message', show_message: 'show_message', hide_message: 'hide_message', + create_message: 'create_message', } /** @@ -86,13 +87,13 @@ const actionOptions = { default: 1, min: 1, max: 99, - tooltip: 'Index of a timer to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second timer from the top, set `index=2`', + tooltip: 'Index of a timer to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second timer from the top, set `index=2`.', }, { id: 'timer_id', type: 'textinput', label: 'Timer ID', - tooltip: 'The ID of the timer you want to target', + tooltip: 'The ID of the timer you want to target.', }, ], message: [ @@ -110,7 +111,41 @@ const actionOptions = { id: 'message_id', type: 'textinput', label: 'Message ID', - tooltip: 'The ID of the message you want to target', + tooltip: 'The ID of the message you want to target.', + }, + ], + messageCreate: [ + { + id: 'text', + type: 'textinput', + label: 'Message text', + tooltip: 'Write the text content of the message.', + }, + { + id: 'color', + type: 'dropdown', + label: 'Text color', + tooltip: 'Choose a text color for the message, default color is white.', + choices: [ + { id: 'white', label: 'White' }, + { id: 'green', label: 'Green' }, + { id: 'red', label: 'Red' }, + ], + default: 'white', + }, + { + id: 'bold', + type: 'checkbox', + label: 'Bold text', + default: false, + tooltip: 'Check to make the message text bold.', + }, + { + id: 'uppercase', + type: 'checkbox', + label: 'Uppercase text', + default: false, + tooltip: 'Check to make the message text uppercase.', }, ], } @@ -266,6 +301,12 @@ export function loadActions (instance) { options: actionOptions.message, callback: actionCallback, }, + [actionIdType.create_message]: { + name: 'Message: Create new message', + description: 'Creates a new message in the room', + options: actionOptions.messageCreate, + callback: actionCallback, + }, // Developer and utility actions [actionIdType.test_auth]: { diff --git a/src/assets.js b/src/assets.js index daba39d..0a5e077 100644 --- a/src/assets.js +++ b/src/assets.js @@ -36,4 +36,5 @@ export const icons = { // Message message: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwQGBwkKC/wM/f7/7VrqgAAABrSURBVEjHY2AYBYRBzjsE2IpbGes7ZJCAUx03iroDONXxoah7MKpuVN2gVMeJom4BTnXM95CUvVXAnZE0Vq1aDVTyZhUQFOHPmixAdYVEZGGguqsMRKl7rUCcukKiig7mq6PF5ygYBUMEAACZJi4Vt/I3cwAAAABJRU5ErkJggg==', messageOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAADcSURBVFjD7dbRDoIwDAXQu6JDRWTr+v/f6gOaMBEIXR97P+AkbZq7AR6POoGZ0LP8TY5nuYcID7KZ/iTHshs+ydGBd3p7gy2H3pbbHVhzLfQy5YC7LYcLm3E3AKBsxclEmwNrOOEOAGIx4kRuGxej5OQZAITRihP+u0A1JyUCQMdG3HeBkxUneTVwEyd8AYArt3DVdPXFJAXXVef7JABhLtVCqoIaU0op5eXF9Kqnp2qVmRvColQfjVyJdakytXCZfkuVG7jPoMtSHbRcV+L6VeLgPy+Px+PxeA7zBmxuLz3gMRqIAAAAAElFTkSuQmCC', + messageNew: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA2UExURQAAAP////////////////////////////////////////////////////////////////////FjxvwAAAARdFJOUwAQIDBAYHB/gI+QoL/Az9/vODCOcwAAAJVJREFUWMPt1dsKhCAUheGlox2cPPT+LzvUFDSRENsNwbD+qxL8QBQ2wFhbXZ4vS16i+blaJ+BSncsC7rh/AMLxv5FzgCP3MBfckgHM+jE0cvdWn+L638OOfCj/xY1Ar8idE3BTXYsC7lVqWrGS2WPfcWmfGTluBZG2t11pMDrjduWKB/S4ZKHIaR30e8MejDHGGJP0AY9hJJdzc693AAAAAElFTkSuQmCC', } diff --git a/src/presets.js b/src/presets.js index 9f5d953..c7f4a6c 100644 --- a/src/presets.js +++ b/src/presets.js @@ -408,6 +408,24 @@ function generatePresets () { }, feedbacks: [], }, + { + name: 'Create message', + actionId: actionIdType.create_message, + actionOptions: { + text: 'New message', + color: 'white', + }, + style: { + size: '14', + text: 'Create', + alignment: 'center:bottom', + png64: icons.messageNew, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, ], } From 9888919826686559f63014ace960d73683eb483c Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:15:22 +0100 Subject: [PATCH 08/18] fix: Type issues related to Node.js timers --- src/state.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/state.js b/src/state.js index 9ea5270..6526d8a 100644 --- a/src/state.js +++ b/src/state.js @@ -5,7 +5,7 @@ import { variableType } from './variables.js' // // Timekeeper service // -/** @type {NodeJS.Timer | null} */ +/** @type {NodeJS.Timeout | null} */ let timerKeeperId = null /** @@ -16,6 +16,7 @@ let timerKeeperId = null */ function startTimeKeeper () { if (timerKeeperId !== null) { return } + // @ts-expect-error: NodeJS.Timeout/Timer don't play well with TS atm timerKeeperId = setInterval(updatePlaybackState.bind(this), 500) } From 70a3fa9c3356fb826047a9110e42118900a71780 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:52:57 +0100 Subject: [PATCH 09/18] feat: add separate hour/minute/second presets add variables and presets, refactor time conversion and formatting, add tests --- package.json | 3 +- src/presets.js | 49 ++++ src/state.js | 19 +- src/types.js | 31 +- src/utils.js | 130 ++++----- src/variables.js | 6 + tests/utils.test.js | 45 +++ yarn.lock | 685 ++++++++++++++++++++++---------------------- 8 files changed, 543 insertions(+), 425 deletions(-) create mode 100644 tests/utils.test.js diff --git a/package.json b/package.json index 0ed1e65..023ac29 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "main": "src/index.js", "type": "module", "scripts": { - "lint": "eslint ./src" + "lint": "eslint ./src", + "test": "node --test" }, "license": "MIT", "repository": { diff --git a/src/presets.js b/src/presets.js index c7f4a6c..33b5473 100644 --- a/src/presets.js +++ b/src/presets.js @@ -199,6 +199,55 @@ function generatePresets () { getFeedbackDefaults(feedbackType.isWarningRed), ], }, + { + name: 'Timer remaining, hours', + actionId: '', + style: { + size: 'auto', + text: `\n$(stagetimer:${variableType.currentTimerRemainingHours})`, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isOnTime), + getFeedbackDefaults(feedbackType.isOverTime), + getFeedbackDefaults(feedbackType.isWarningYellow), + getFeedbackDefaults(feedbackType.isWarningRed), + ], + }, + { + name: 'Timer remaining, minutes', + actionId: '', + style: { + size: 'auto', + text: `\n$(stagetimer:${variableType.currentTimerRemainingMinutes})`, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isOnTime), + getFeedbackDefaults(feedbackType.isOverTime), + getFeedbackDefaults(feedbackType.isWarningYellow), + getFeedbackDefaults(feedbackType.isWarningRed), + ], + }, + { + name: 'Timer remaining, seconds', + actionId: '', + style: { + size: 'auto', + text: `\n$(stagetimer:${variableType.currentTimerRemainingSeconds})`, + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [ + getFeedbackDefaults(feedbackType.isOnTime), + getFeedbackDefaults(feedbackType.isOverTime), + getFeedbackDefaults(feedbackType.isWarningYellow), + getFeedbackDefaults(feedbackType.isWarningRed), + ], + }, + { name: 'Timer status', actionId: '', diff --git a/src/state.js b/src/state.js index 6526d8a..2d5f7d8 100644 --- a/src/state.js +++ b/src/state.js @@ -1,5 +1,5 @@ import { feedbackType } from './feedbacks.js' -import { formatDuration, createTimeset } from './utils.js' +import { createTimeset } from './utils.js' import { variableType } from './variables.js' // @@ -17,7 +17,7 @@ let timerKeeperId = null function startTimeKeeper () { if (timerKeeperId !== null) { return } // @ts-expect-error: NodeJS.Timeout/Timer don't play well with TS atm - timerKeeperId = setInterval(updatePlaybackState.bind(this), 500) + timerKeeperId = setInterval(updatePlaybackState.bind(this), 250) } /** @@ -140,7 +140,7 @@ export function updatePlaybackState (newState) { const updatedState = createTimeset(newState || instance.state.playback_status) updatedState.phase = getTimerPhase( - updatedState.remaining ?? 0, + updatedState.remainingAsMs ?? 0, instance.state.timer.wrap_up_yellow, instance.state.timer.wrap_up_red, ) @@ -157,11 +157,14 @@ export function updatePlaybackState (newState) { instance.setVariableValues({ [variableType.currentTimerId]: updatedState.currentTimerId ?? undefined, - [variableType.currentTimerDuration]: formatDuration(updatedState.total), - [variableType.currentTimerDurationAsMs]: updatedState.total, + [variableType.currentTimerDuration]: updatedState.totalAsHuman, + [variableType.currentTimerDurationAsMs]: updatedState.totalAsMs, - [variableType.currentTimerRemaining]: formatDuration(updatedState.remaining), - [variableType.currentTimerRemainingAsMs]: updatedState.remaining, + [variableType.currentTimerRemaining]: updatedState.remainingAsHuman, + [variableType.currentTimerRemainingAsMs]: updatedState.remainingAsMs, + [variableType.currentTimerRemainingHours]: updatedState.remainingHours, + [variableType.currentTimerRemainingMinutes]: updatedState.remainingMinutes, + [variableType.currentTimerRemainingSeconds]: updatedState.remainingSeconds, }) instance.checkFeedbacks( @@ -193,7 +196,7 @@ export function updateTimerState (newState) { // Update `phase` using `playback_status` and `timer` state instance.state.playback_status.phase = getTimerPhase( - instance.state.playback_status.remaining ?? 0, + instance.state.playback_status.remainingAsMs ?? 0, instance.state.timer.wrap_up_yellow, instance.state.timer.wrap_up_red, ) diff --git a/src/types.js b/src/types.js index 54a135d..8ace032 100644 --- a/src/types.js +++ b/src/types.js @@ -119,8 +119,13 @@ * @property {number} kickoff * @property {number} deadline * @property {number} lastStop - * @property {number} [total] - * @property {number} [remaining] + * @property {number} [totalAsMs] + * @property {string} [totalAsHuman] + * @property {number} [remainingAsMs] + * @property {string} [remainingAsHuman] + * @property {string} [remainingHours] + * @property {string} [remainingMinutes] + * @property {string} [remainingSeconds] * @property {import('./state.js').timerPhases} [phase] */ @@ -148,6 +153,28 @@ * @property {number} wrap_up_red */ +/** + * A DHMS object containing the components for calculating and formatting durations. + * + * @typedef {object} DhmsObj + * @property { 0 | 1 } negative + * @property {number} days + * @property {number} hours + * @property {number} minutes + * @property {number} seconds + * @property {number} hoursSum + */ + +/** + * An object containing formatted duration components + * + * @typedef {object} FormattedDhmsObj + * @property {string} hhh formatted hoursSum + * @property {string} mm formatted minutes + * @property {string} ss formatted seconds + * @property {string} human hhh:mm:ss + */ + /** * Custom type for defining buttons for Presets, * that will be turned into {@link CompanionPresetDefinitions} diff --git a/src/utils.js b/src/utils.js index 0b9e33c..785ce09 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,34 +1,53 @@ -import { format } from 'date-fns' - /** + * Pad with zeroes + * * @param {number} number - * @returns {boolean} + * @returns {string} */ -export function isNegative (number) { - return Math.sign(number) == -1 ? true : false +function zeroPad (number) { + return String(number).padStart(2, '0') } -// -// Utility functions from Stagetimer.io -// - /** - * Correction for millisecond rounding + * Converts a duration of time (in milliseconds) into a Dhms object. + * Adapted from `millisecondsToDhms()` in Stagetimer codebase. * - * @param {number} ms Duration of time as milliseconds. - * @returns {number} + * @param {number} ms A duration as milliseconds + * @returns {DhmsObj} */ -function floor50 (ms) { - return Math.floor(ms / 50) * 50 +export function millisecondsToDhms (ms = 0) { + const negative = ms < 0 ? 1 : 0 + const absMs = Math.abs(ms) + + return { + negative: negative, + days : Math.floor(absMs / 86400000) || 0, + hours : Math.floor((absMs % 86400000) / 3600000) || 0, + minutes : Math.floor((absMs % 3600000) / 60000) || 0, + seconds : Math.floor((absMs % 60000) / 1000) || 0, + hoursSum: Math.floor(absMs / 3600000) || 0, + } } /** - * Creates new zeroed timestamp + * Formats a Dhms object into formatted segments. * - * @returns {number} + * @param {DhmsObj} dhms + * @returns {FormattedDhmsObj} */ -function zero () { - return new Date().setHours(0, 0, 0, 0) +export function dhmsToFormatted (dhms) { + const prefix = dhms.negative ? '-' : '' + + const hhh = `${prefix}${dhms.hoursSum}` + const mm = zeroPad(dhms.minutes) + const ss = zeroPad(dhms.seconds) + + return { + human: `${hhh}:${mm}:${ss}`, + hhh, + mm, + ss, + } } /** @@ -54,63 +73,26 @@ export function createTimeset (timeset, now = Date.now()) { // Correct edge-case where left > total if (remaining > total) remaining = total - return { - ...timeset, - total: floor50(total), - remaining: floor50(remaining), - } -} + // Prepare total + const totalAsMsRounded = Math.ceil(total/1000) * 1000 + const totalAsDhms = millisecondsToDhms(totalAsMsRounded) + const totalFormatted = dhmsToFormatted(totalAsDhms) -/** - * Formats a duration of time (in milliseconds) into a human-readable string. - * Adapted from `formatDuration()` in Stagetimer codebase. - * - * @param {number} milliseconds - The duration in milliseconds to format. - * @param {object} [options] - Formatting options. - * @param {boolean} [options.includeH] - Whether to include hours in the output. - * @param {boolean} [options.includeS] - Whether to include seconds in the output. - * @param {boolean} [options.includeMs] - Whether to include milliseconds in the output. - * @param {boolean} [options.includePrefix] - Whether to include a '-' prefix for negative durations. - * @param {string} [options.customFormat] - A custom format string to use instead of the default format. - * - * @returns {string} The formatted duration string. - */ -export function formatDuration ( - milliseconds = 0, - { includeH = true, - includeS = true, - includeMs = false, - includePrefix = true, - } = {}, -) { - // Return an empty string if milliseconds is not a number or is NaN - if (typeof milliseconds !== 'number' || isNaN(milliseconds)) return '' - - const withMs = includeMs - const withSec = includeS || Math.abs(milliseconds) < 3600000 - const withHrs = includeH || Math.abs(milliseconds) >= 3600000 - - // Determine the prefix of the output string. - const prefix = isNegative(milliseconds) ? '-' : '' - - // Determine the format string based on the options. - let formatStr = 'm' - if (withMs) formatStr = 'm:ss.S' - else if (withSec) formatStr = 'm:ss' - if (withHrs) formatStr = 'm' + formatStr + // Prepare remaining + const remainingAsMsRounded = Math.ceil(remaining/1000) * 1000 + const remainingAsDhms = millisecondsToDhms(remainingAsMsRounded) + const remainingFormatted = dhmsToFormatted(remainingAsDhms) - // Format the duration into the output string - let output = format(zero() + Math.abs(milliseconds), formatStr) - - // Add hours to the output if necessary - if (withHrs) { - output = Math.floor(Math.abs(milliseconds) / 3600000) + ':' + output - } - - // Add optional prefix - if (includePrefix) { - output = prefix + output + return { + ...timeset, + // Total + totalAsMs : totalAsMsRounded, + totalAsHuman : totalFormatted.human, + // Remaining + remainingAsMs : remainingAsMsRounded, + remainingAsHuman: remainingFormatted.human, + remainingHours : remainingFormatted.hhh, + remainingMinutes: remainingFormatted.mm, + remainingSeconds: remainingFormatted.ss, } - - return output } diff --git a/src/variables.js b/src/variables.js index d5696f8..bc14875 100644 --- a/src/variables.js +++ b/src/variables.js @@ -18,6 +18,9 @@ export const variableType = { currentTimerRemaining: 'currentTimerRemaining', currentTimerRemainingAsMs: 'currentTimerRemainingAsMs', + currentTimerRemainingHours: 'currentTimerRemainingHours', + currentTimerRemainingMinutes: 'currentTimerRemainingMinutes', + currentTimerRemainingSeconds: 'currentTimerRemainingSeconds', } /** @type {CompanionVariableDefinition[]} */ @@ -35,6 +38,9 @@ const variables = [ { variableId: variableType.currentTimerRemaining, name: 'Timer remaining time' }, { variableId: variableType.currentTimerRemainingAsMs, name: 'Timer remaining time (ms)' }, + { variableId: variableType.currentTimerRemainingHours, name: 'Timer remaining time (hours)' }, + { variableId: variableType.currentTimerRemainingMinutes, name: 'Timer remaining time (minutes)' }, + { variableId: variableType.currentTimerRemainingSeconds, name: 'Timer remaining time (seconds)' }, ] /** diff --git a/tests/utils.test.js b/tests/utils.test.js new file mode 100644 index 0000000..dcff8ed --- /dev/null +++ b/tests/utils.test.js @@ -0,0 +1,45 @@ +import { describe, test } from 'node:test' +import { deepEqual } from 'node:assert/strict' + +import { millisecondsToDhms, dhmsToFormatted } from '../src/utils.js' + +describe('utils.millisecondsToDhms', () => { + test('conversion', () => { + deepEqual(millisecondsToDhms(3599989000), { negative: 0, days: 41, hours: 15, minutes: 59, seconds: 49, hoursSum: 999 }) + deepEqual(millisecondsToDhms(97323400), { negative: 0, days: 1, hours: 3, minutes: 2, seconds: 3, hoursSum: 27 }) + deepEqual(millisecondsToDhms(3723400), { negative: 0, days: 0, hours: 1, minutes: 2, seconds: 3, hoursSum: 1 }) + deepEqual(millisecondsToDhms(3600000), { negative: 0, days: 0, hours: 1, minutes: 0, seconds: 0, hoursSum: 1 }) + deepEqual(millisecondsToDhms(60000), { negative: 0, days: 0, hours: 0, minutes: 1, seconds: 0, hoursSum: 0 }) + deepEqual(millisecondsToDhms(1500), { negative: 0, days: 0, hours: 0, minutes: 0, seconds: 1, hoursSum: 0 }) + deepEqual(millisecondsToDhms(1000), { negative: 0, days: 0, hours: 0, minutes: 0, seconds: 1, hoursSum: 0 }) + deepEqual(millisecondsToDhms(500), { negative: 0, days: 0, hours: 0, minutes: 0, seconds: 0, hoursSum: 0 }) + deepEqual(millisecondsToDhms(0), { negative: 0, days: 0, hours: 0, minutes: 0, seconds: 0, hoursSum: 0 }) + deepEqual(millisecondsToDhms(/* none */), { negative: 0, days: 0, hours: 0, minutes: 0, seconds: 0, hoursSum: 0 }) + deepEqual(millisecondsToDhms(-500), { negative: 1, days: 0, hours: 0, minutes: 0, seconds: 0, hoursSum: 0 }) + deepEqual(millisecondsToDhms(-1000), { negative: 1, days: 0, hours: 0, minutes: 0, seconds: 1, hoursSum: 0 }) + deepEqual(millisecondsToDhms(-1500), { negative: 1, days: 0, hours: 0, minutes: 0, seconds: 1, hoursSum: 0 }) + deepEqual(millisecondsToDhms(-3723400), { negative: 1, days: 0, hours: 1, minutes: 2, seconds: 3, hoursSum: 1 }) + deepEqual(millisecondsToDhms(-97323400), { negative: 1, days: 1, hours: 3, minutes: 2, seconds: 3, hoursSum: 27 }) + deepEqual(millisecondsToDhms(-3599989000), { negative: 1, days: 41, hours: 15, minutes: 59, seconds: 49, hoursSum: 999 }) + }) +}) +describe('utils.dhmsToFormatted', () => { + test('formatting', () => { + deepEqual(dhmsToFormatted(millisecondsToDhms(3599989000)), { human: '999:59:49', hhh: '999', mm: '59', ss: '49' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(97323400)), { human: '27:02:03', hhh: '27', mm: '02', ss: '03' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(3723400)), { human: '1:02:03', hhh: '1', mm: '02', ss: '03' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(3600000)), { human: '1:00:00', hhh: '1', mm: '00', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(60000)), { human: '0:01:00', hhh: '0', mm: '01', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(1500)), { human: '0:00:01', hhh: '0', mm: '00', ss: '01' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(1000)), { human: '0:00:01', hhh: '0', mm: '00', ss: '01' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(500)), { human: '0:00:00', hhh: '0', mm: '00', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(0)), { human: '0:00:00', hhh: '0', mm: '00', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(/* none */)), { human: '0:00:00', hhh: '0', mm: '00', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-500)), { human: '-0:00:00', hhh: '-0', mm: '00', ss: '00' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-1000)), { human: '-0:00:01', hhh: '-0', mm: '00', ss: '01' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-1500)), { human: '-0:00:01', hhh: '-0', mm: '00', ss: '01' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-3723400)), { human: '-1:02:03', hhh: '-1', mm: '02', ss: '03' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-97323400)), { human: '-27:02:03', hhh: '-27', mm: '02', ss: '03' }) + deepEqual(dhmsToFormatted(millisecondsToDhms(-3599989000)), { human: '-999:59:49', hhh: '-999', mm: '59', ss: '49' }) + }) +}) diff --git a/yarn.lock b/yarn.lock index c8c8382..3c4c166 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,19 +4,19 @@ "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== "@babel/runtime@^7.21.0": version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz" integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== dependencies: regenerator-runtime "^0.13.11" -"@companion-module/base@~1.4.1": +"@companion-module/base@^1.4.1", "@companion-module/base@~1.4.1": version "1.4.1" - resolved "https://registry.yarnpkg.com/@companion-module/base/-/base-1.4.1.tgz#4ddc4ba636b672bcbbc3dc4645634007a49d6189" + resolved "https://registry.npmjs.org/@companion-module/base/-/base-1.4.1.tgz" integrity sha512-xg5OX33ptfFsV/drfeNTHID7hp9f2cdp8V+7Pj8uartdNstCr28W3bAy8xRz+XRFKxQVkJcL2LqrkYZ8GGfetw== dependencies: "@sentry/node" "^7.36.0" @@ -32,7 +32,7 @@ "@companion-module/tools@^1.3.2": version "1.3.2" - resolved "https://registry.yarnpkg.com/@companion-module/tools/-/tools-1.3.2.tgz#97baf6678d719b901709eefd7adb2f5652133dc1" + resolved "https://registry.npmjs.org/@companion-module/tools/-/tools-1.3.2.tgz" integrity sha512-5Ou/8a2tEbLlq9ousC9DsPffdt/eOK39gqllJiEmiu7xumltfPZT5GXLrgWKPKHBkZmwHj1FJw/9OgXyecAxuw== dependencies: "@typescript-eslint/eslint-plugin" "^5.59.9" @@ -51,24 +51,24 @@ "@discoveryjs/json-ext@^0.5.0": version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== "@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.5.0": version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz" integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== "@eslint/eslintrc@^2.1.0": version "2.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.0.tgz#82256f164cc9e0b59669efc19d57f8092706841d" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz" integrity sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A== dependencies: ajv "^6.12.4" @@ -83,12 +83,12 @@ "@eslint/js@8.44.0": version "8.44.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.44.0.tgz#961a5903c74139390478bdc808bcde3fc45ab7af" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz" integrity sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw== "@humanwhocodes/config-array@^0.11.10": version "0.11.10" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz" integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" @@ -97,17 +97,17 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^1.2.1": version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@jridgewell/gen-mapping@^0.3.0": version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -116,35 +116,35 @@ "@jridgewell/resolve-uri@3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.3": version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz" integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz" integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== dependencies: "@jridgewell/resolve-uri" "3.1.0" @@ -152,20 +152,20 @@ "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -173,7 +173,7 @@ "@sentry-internal/tracing@7.57.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.57.0.tgz#cb761931b635f8f24c84be0eecfacb8516b20551" + resolved "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.57.0.tgz" integrity sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A== dependencies: "@sentry/core" "7.57.0" @@ -183,7 +183,7 @@ "@sentry/core@7.57.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.57.0.tgz#65093d739c04f320a54395a21be955fcbe326acb" + resolved "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz" integrity sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw== dependencies: "@sentry/types" "7.57.0" @@ -192,7 +192,7 @@ "@sentry/node@^7.36.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.57.0.tgz#31052f5988ed4496d7f3ff925240cf9b02d09941" + resolved "https://registry.npmjs.org/@sentry/node/-/node-7.57.0.tgz" integrity sha512-63mjyUVM6sfJFVQ5TGVRVGUsoEfESl5ABzIW1W0s9gUiQPaG8SOdaQJglb2VNrkMYxnRHgD8Q9LUh/qcmUyPGw== dependencies: "@sentry-internal/tracing" "7.57.0" @@ -206,19 +206,19 @@ "@sentry/tracing@^7.36.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.57.0.tgz#8bd07317db7b88ec5ecae48ad680e269af71b54d" + resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.57.0.tgz" integrity sha512-D8eKJMYN529mDP9lsOLyhe0Rf9Qiexo7Ul4+MQwDlwRr9c9tc0AdGwFlnKGvCMDh7ucITzvZkMZDHBapU3WHNQ== dependencies: "@sentry-internal/tracing" "7.57.0" "@sentry/types@7.57.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.57.0.tgz#4fdb80cbd49ba034dd8d9be0c0005a016d5db3ce" + resolved "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz" integrity sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w== "@sentry/utils@7.57.0": version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.57.0.tgz#8253c6fcf35138b4c424234b8da1596e11b98ad8" + resolved "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz" integrity sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg== dependencies: "@sentry/types" "7.57.0" @@ -226,12 +226,12 @@ "@socket.io/component-emitter@~3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== "@types/eslint-scope@^3.7.3": version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz" integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== dependencies: "@types/eslint" "*" @@ -239,7 +239,7 @@ "@types/eslint@*": version "8.40.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.40.2.tgz#2833bc112d809677864a4b0e7d1de4f04d7dac2d" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.2.tgz" integrity sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ== dependencies: "@types/estree" "*" @@ -247,12 +247,12 @@ "@types/estree@*", "@types/estree@^1.0.0": version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz" integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/fs-extra@^11.0.1": version "11.0.1" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.1.tgz#f542ec47810532a8a252127e6e105f487e0a6ea5" + resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.1.tgz" integrity sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA== dependencies: "@types/jsonfile" "*" @@ -260,49 +260,49 @@ "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== "@types/jsonfile@*": version "6.1.1" - resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.1.tgz#ac84e9aefa74a2425a0fb3012bdea44f58970f1b" + resolved "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz" integrity sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png== dependencies: "@types/node" "*" "@types/minimist@^1.2.2": version "1.2.2" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== "@types/node@*": version "20.3.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.3.tgz#329842940042d2b280897150e023e604d11657d6" + resolved "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz" integrity sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw== "@types/node@^18.16.3": version "18.16.19" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.19.tgz#cb03fca8910fdeb7595b755126a8a78144714eea" + resolved "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz" integrity sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA== "@types/ps-tree@^1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@types/ps-tree/-/ps-tree-1.1.2.tgz#5c60773a38ffb1402e049902a7b7a8d3c67cd59a" + resolved "https://registry.npmjs.org/@types/ps-tree/-/ps-tree-1.1.2.tgz" integrity sha512-ZREFYlpUmPQJ0esjxoG1fMvB2HNaD3z+mjqdSosZvd3RalncI9NEur73P8ZJz4YQdL64CmV1w0RuqoRUlhQRBw== "@types/semver@^7.3.12": version "7.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== "@types/which@^3.0.0": version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/which/-/which-3.0.0.tgz#849afdd9fdcb0b67339b9cfc80fa6ea4e0253fc5" + resolved "https://registry.npmjs.org/@types/which/-/which-3.0.0.tgz" integrity sha512-ASCxdbsrwNfSMXALlC3Decif9rwDMu+80KGp5zI2RLRotfMsTv7fHL8W8VDp24wymzDyIFudhUeSCugrgRFfHQ== "@typescript-eslint/eslint-plugin@^5.59.9": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz#a1a5290cf33863b4db3fb79350b3c5275a7b1223" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz" integrity sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g== dependencies: "@eslint-community/regexpp" "^4.4.0" @@ -316,9 +316,9 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.59.9": +"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.59.9": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.61.0.tgz#7fbe3e2951904bb843f8932ebedd6e0635bffb70" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz" integrity sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg== dependencies: "@typescript-eslint/scope-manager" "5.61.0" @@ -328,7 +328,7 @@ "@typescript-eslint/scope-manager@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz#b670006d069c9abe6415c41f754b1b5d949ef2b2" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.61.0.tgz" integrity sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw== dependencies: "@typescript-eslint/types" "5.61.0" @@ -336,7 +336,7 @@ "@typescript-eslint/type-utils@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz#e90799eb2045c4435ea8378cb31cd8a9fddca47a" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz" integrity sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg== dependencies: "@typescript-eslint/typescript-estree" "5.61.0" @@ -346,12 +346,12 @@ "@typescript-eslint/types@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.61.0.tgz#e99ff11b5792d791554abab0f0370936d8ca50c0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.61.0.tgz" integrity sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ== "@typescript-eslint/typescript-estree@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz#4c7caca84ce95bb41aa585d46a764bcc050b92f3" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.61.0.tgz" integrity sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw== dependencies: "@typescript-eslint/types" "5.61.0" @@ -364,7 +364,7 @@ "@typescript-eslint/utils@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.61.0.tgz#5064838a53e91c754fffbddd306adcca3fe0af36" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz" integrity sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -378,15 +378,15 @@ "@typescript-eslint/visitor-keys@5.61.0": version "5.61.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz#c79414fa42158fd23bd2bb70952dc5cdbb298140" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.61.0.tgz" integrity sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg== dependencies: "@typescript-eslint/types" "5.61.0" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": +"@webassemblyjs/ast@^1.11.5", "@webassemblyjs/ast@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz" integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" @@ -394,22 +394,22 @@ "@webassemblyjs/floating-point-hex-parser@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz" integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== "@webassemblyjs/helper-api-error@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== "@webassemblyjs/helper-buffer@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz" integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz" integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.6" @@ -418,12 +418,12 @@ "@webassemblyjs/helper-wasm-bytecode@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== "@webassemblyjs/helper-wasm-section@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz" integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -433,26 +433,26 @@ "@webassemblyjs/ieee754@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz" integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz" integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== "@webassemblyjs/wasm-edit@^1.11.5": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz" integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -466,7 +466,7 @@ "@webassemblyjs/wasm-gen@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz" integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -477,7 +477,7 @@ "@webassemblyjs/wasm-opt@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz" integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -485,9 +485,9 @@ "@webassemblyjs/wasm-gen" "1.11.6" "@webassemblyjs/wasm-parser" "1.11.6" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": +"@webassemblyjs/wasm-parser@^1.11.5", "@webassemblyjs/wasm-parser@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz" integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -499,7 +499,7 @@ "@webassemblyjs/wast-printer@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz" integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== dependencies: "@webassemblyjs/ast" "1.11.6" @@ -507,59 +507,59 @@ "@webpack-cli/configtest@^2.1.1": version "2.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + resolved "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz" integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== "@webpack-cli/info@^2.0.2": version "2.0.2" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + resolved "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz" integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== "@webpack-cli/serve@^2.0.5": version "2.0.5" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + resolved "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== "@xtuc/ieee754@^1.2.0": version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== acorn-import-assertions@^1.9.0: version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -569,7 +569,7 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: ajv@^8.12.0: version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" @@ -579,39 +579,39 @@ ajv@^8.12.0: ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== author-regex@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450" + resolved "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz" integrity sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -619,14 +619,14 @@ brace-expansion@^1.1.7: braces@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" -browserslist@^4.14.5: +browserslist@^4.14.5, "browserslist@>= 4.21.0": version "4.21.9" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz" integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== dependencies: caniuse-lite "^1.0.30001503" @@ -636,29 +636,29 @@ browserslist@^4.14.5: buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== builtins@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz" integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== dependencies: semver "^7.0.0" callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001503: version "1.0.30001512" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz#7450843fb581c39f290305a83523c7a9ef0d4cb4" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz" integrity sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw== chalk@^4.0.0: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -666,22 +666,22 @@ chalk@^4.0.0: chalk@^5.2.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== chownr@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== chrome-trace-event@^1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== clone-deep@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== dependencies: is-plain-object "^2.0.4" @@ -690,44 +690,44 @@ clone-deep@^4.0.1: color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== colorette@^2.0.14: version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== commander@^10.0.1: version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== commander@^2.20.0: version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== cookie@^0.4.1: version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -736,66 +736,66 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: data-uri-to-buffer@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== date-fns@^2.30.0: version "2.30.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz" integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== dependencies: "@babel/runtime" "^7.21.0" "debounce-fn@github:julusian/debounce-fn#4.0.0-maxWaithack.0": version "4.0.0-maxWaithack.0" - resolved "https://codeload.github.com/julusian/debounce-fn/tar.gz/3ca54d1526c19f541fe6f103abbceda31554caa9" + resolved "git+ssh://git@github.com/julusian/debounce-fn.git#3ca54d1526c19f541fe6f103abbceda31554caa9" dependencies: mimic-fn "^3.0.0" -debug@4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" duplexer@~0.1.1: version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== ejson@^2.2.3: version "2.2.3" - resolved "https://registry.yarnpkg.com/ejson/-/ejson-2.2.3.tgz#2b18c2d8f5d61a5cfc6e3eab72c3343909e7afd2" + resolved "https://registry.npmjs.org/ejson/-/ejson-2.2.3.tgz" integrity sha512-hsFvJp6OpGxFRQfBR3PSxFpaPALdHDY+SB3TRbMpLWNhvu8GzLiZutof5+/DFd2QekZo3KyXau75ngdJqQUSrw== electron-to-chromium@^1.4.431: version "1.4.450" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz#df232c961ee9bf4e8980f86e96a6e9f291720138" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz" integrity sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw== engine.io-client@~6.5.1: version "6.5.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.1.tgz#1735fb8ae3bae5ae13115e18d2f484daf005dd9c" + resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.1.tgz" integrity sha512-hE5wKXH8Ru4L19MbM1GgYV/2Qo54JSMh1rlJbfpa40bEWkCKNo3ol2eOtGmowcr+ysgbI7+SGL+by42Q3pt/Ng== dependencies: "@socket.io/component-emitter" "~3.1.0" @@ -806,12 +806,12 @@ engine.io-client@~6.5.1: engine.io-parser@~5.1.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.1.0.tgz#d593d6372d7f79212df48f807b8cace1ea1cb1b8" + resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz" integrity sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w== enhanced-resolve@^5.15.0: version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz" integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== dependencies: graceful-fs "^4.2.4" @@ -819,32 +819,32 @@ enhanced-resolve@^5.15.0: envinfo@^7.7.3: version "7.10.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13" + resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz" integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== es-module-lexer@^1.2.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz" integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-config-prettier@^8.8.0: version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz" integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-plugin-es-x@^7.1.0: version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz#f0d5421e658cca95c1cfb2355831851bdc83322d" + resolved "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz" integrity sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw== dependencies: "@eslint-community/eslint-utils" "^4.1.2" @@ -852,7 +852,7 @@ eslint-plugin-es-x@^7.1.0: eslint-plugin-n@^16.0.0: version "16.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz#baa62bb3af52940a53ba15386348ad9b0b425ada" + resolved "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz" integrity sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" @@ -866,14 +866,14 @@ eslint-plugin-n@^16.0.0: eslint-plugin-prettier@^4.2.1: version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz" integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@^5.1.1, eslint-scope@5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -881,7 +881,7 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: eslint-scope@^7.2.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz" integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" @@ -889,12 +889,12 @@ eslint-scope@^7.2.0: eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz" integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== -eslint@^8.42.0: +eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@^8.42.0, eslint@>=7.0.0, eslint@>=7.28.0, eslint@>=8: version "8.44.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.44.0.tgz#51246e3889b259bbcd1d7d736a0c10add4f0e500" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz" integrity sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -939,7 +939,7 @@ eslint@^8.42.0: espree@^9.6.0: version "9.6.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz" integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== dependencies: acorn "^8.9.0" @@ -948,36 +948,36 @@ espree@^9.6.0: esquery@^1.4.2: version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== event-stream@=3.3.4: version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz" integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== dependencies: duplexer "~0.1.1" @@ -990,27 +990,27 @@ event-stream@=3.3.4: eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.2.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.2.11, fast-glob@^3.2.9: version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz" integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -1021,29 +1021,29 @@ fast-glob@^3.2.11, fast-glob@^3.2.9: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastest-levenshtein@^1.0.12: version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" fetch-blob@^3.1.2, fetch-blob@^3.1.4: version "3.2.0" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz" integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== dependencies: node-domexception "^1.0.0" @@ -1051,21 +1051,21 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4: file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" find-up@^4.0.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1073,7 +1073,7 @@ find-up@^4.0.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -1081,7 +1081,7 @@ find-up@^5.0.0: find-up@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + resolved "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz" integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== dependencies: locate-path "^7.1.0" @@ -1089,7 +1089,7 @@ find-up@^6.3.0: flat-cache@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: flatted "^3.1.0" @@ -1097,24 +1097,24 @@ flat-cache@^3.0.4: flatted@^3.1.0: version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== formdata-polyfill@^4.0.10: version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== dependencies: fetch-blob "^3.1.2" from@~0: version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + resolved "https://registry.npmjs.org/from/-/from-0.1.7.tgz" integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== fs-extra@^11.1.1: version "11.1.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz" integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== dependencies: graceful-fs "^4.2.0" @@ -1123,48 +1123,48 @@ fs-extra@^11.1.1: fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== fx@*: version "28.0.0" - resolved "https://registry.yarnpkg.com/fx/-/fx-28.0.0.tgz#67087b31377039bab42f51db32c8758ccb4708e8" + resolved "https://registry.npmjs.org/fx/-/fx-28.0.0.tgz" integrity sha512-vKQDA9g868cZiW8ulgs2uN1yx1i7/nsS33jTMOxekk0Z03BJLffVcdW6AVD32fWb3E6RtmWWuBXBZOk8cLXFNQ== glob-parent@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob-to-regexp@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^7.1.3: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1176,14 +1176,14 @@ glob@^7.1.3: globals@^13.19.0: version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + resolved "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz" integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== dependencies: type-fest "^0.20.2" globby@^11.1.0: version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -1195,7 +1195,7 @@ globby@^11.1.0: globby@^13.1.4: version "13.2.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.1.tgz#986d44187ba6a9fc4aa9b16caf0ab9a04db94ae9" + resolved "https://registry.npmjs.org/globby/-/globby-13.2.1.tgz" integrity sha512-DPCBxctI7dN4EeIqjW2KGqgdcUMbrhJ9AzON+PlxCtvppWhubTLD4+a0GFxiym14ZvacUydTPjLPc2DlKz7EIg== dependencies: dir-glob "^3.0.1" @@ -1206,29 +1206,29 @@ globby@^13.1.4: graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -1236,12 +1236,12 @@ https-proxy-agent@^5.0.0: ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -1249,7 +1249,7 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: import-local@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -1257,12 +1257,12 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1270,63 +1270,63 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== interpret@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + resolved "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== is-core-module@^2.11.0, is-core-module@^2.12.1: version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz" integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== dependencies: has "^1.0.3" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-path-inside@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== jest-worker@^27.4.5: version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" @@ -1335,34 +1335,34 @@ jest-worker@^27.4.5: js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" json-parse-even-better-errors@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -1371,12 +1371,12 @@ jsonfile@^6.0.1: kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" @@ -1384,65 +1384,65 @@ levn@^0.4.1: loader-runner@^4.2.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" locate-path@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz" integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== dependencies: p-locate "^6.0.0" lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - map-stream@~0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + resolved "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz" integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: braces "^3.0.2" @@ -1450,48 +1450,48 @@ micromatch@^4.0.4: mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.27: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mimic-fn@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimist@^1.2.8: version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass@^3.0.0: version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" minipass@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -1499,42 +1499,42 @@ minizlib@^2.1.1: mkdirp@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== nanoid@^3.3.4: version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== natural-compare-lite@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-domexception@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-fetch@3.3.1: version "3.3.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.1.tgz#b3eea7b54b3a48020e46f4f88b9c5a7430d20b2e" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz" integrity sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow== dependencies: data-uri-to-buffer "^4.0.0" @@ -1543,19 +1543,19 @@ node-fetch@3.3.1: node-releases@^2.0.12: version "2.0.12" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz" integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" optionator@^0.9.3: version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: "@aashutoshrathi/word-wrap" "^1.2.3" @@ -1567,54 +1567,54 @@ optionator@^0.9.3: p-finally@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-limit@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz" integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== dependencies: yocto-queue "^1.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-locate@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz" integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== dependencies: p-limit "^4.0.0" p-queue@^6.6.2: version "6.6.2" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" + resolved "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz" integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== dependencies: eventemitter3 "^4.0.4" @@ -1622,167 +1622,167 @@ p-queue@^6.6.2: p-timeout@^3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz" integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== dependencies: p-finally "^1.0.0" p-timeout@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-4.1.0.tgz#788253c0452ab0ffecf18a62dff94ff1bd09ca0a" + resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz" integrity sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw== p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-author@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f" + resolved "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz" integrity sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw== dependencies: author-regex "^1.0.0" path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-exists@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz" integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pause-stream@0.0.11: version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + resolved "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz" integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== dependencies: through "~2.3" picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" -prettier@^2.8.8: +prettier@^2.8.8, prettier@>=2.0.0: version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== ps-tree@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" + resolved "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz" integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== dependencies: event-stream "=3.3.4" punycode@^2.1.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" rechoir@^0.8.0: version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz" integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== dependencies: resolve "^1.20.0" regenerator-runtime@^0.13.11: version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve@^1.20.0, resolve@^1.22.2: version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== dependencies: is-core-module "^2.11.0" @@ -1791,31 +1791,31 @@ resolve@^1.20.0, resolve@^1.22.2: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" @@ -1824,50 +1824,50 @@ schema-utils@^3.1.1, schema-utils@^3.2.0: semver@^7.0.0, semver@^7.3.7, semver@^7.5.3: version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" serialize-javascript@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz" integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== dependencies: randombytes "^2.1.0" shallow-clone@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== dependencies: kind-of "^6.0.2" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== slash@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slash@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== socket.io-client@^4.7.1: version "4.7.1" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.1.tgz#48e5f703abe4fb0402182bcf9c06b7820fb3453b" + resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.1.tgz" integrity sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w== dependencies: "@socket.io/component-emitter" "~3.1.0" @@ -1877,7 +1877,7 @@ socket.io-client@^4.7.1: socket.io-parser@~4.2.4: version "4.2.4" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz" integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== dependencies: "@socket.io/component-emitter" "~3.1.0" @@ -1885,7 +1885,7 @@ socket.io-parser@~4.2.4: source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -1893,62 +1893,62 @@ source-map-support@~0.5.20: source-map@^0.6.0: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== split@0.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + resolved "https://registry.npmjs.org/split/-/split-0.3.3.tgz" integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== dependencies: through "2" stream-combiner@~0.0.4: version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + resolved "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== dependencies: duplexer "~0.1.1" strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== tar@^6.1.15: version "6.1.15" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" + resolved "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz" integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== dependencies: chownr "^2.0.0" @@ -1960,7 +1960,7 @@ tar@^6.1.15: terser-webpack-plugin@^5.3.7: version "5.3.9" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz" integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== dependencies: "@jridgewell/trace-mapping" "^0.3.17" @@ -1971,7 +1971,7 @@ terser-webpack-plugin@^5.3.7: terser@^5.16.8: version "5.18.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.2.tgz#ff3072a0faf21ffd38f99acc9a0ddf7b5f07b948" + resolved "https://registry.npmjs.org/terser/-/terser-5.18.2.tgz" integrity sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w== dependencies: "@jridgewell/source-map" "^0.3.3" @@ -1981,58 +1981,63 @@ terser@^5.16.8: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through@2, through@~2.3, through@~2.3.1: +through@~2.3, through@~2.3.1, through@2: version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" tslib@^1.8.1: version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== "tslib@^2.4.1 || ^1.9.3", tslib@^2.5.0: version "2.6.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz" integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +"typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta": + version "5.2.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + universalify@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== update-browserslist-db@^1.0.11: version "1.0.11" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz" integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== dependencies: escalade "^3.1.1" @@ -2040,14 +2045,14 @@ update-browserslist-db@^1.0.11: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" watchpack@^2.4.0: version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== dependencies: glob-to-regexp "^0.4.1" @@ -2055,12 +2060,12 @@ watchpack@^2.4.0: web-streams-polyfill@^3.0.3: version "3.2.1" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz" integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== -webpack-cli@^5.1.4: +webpack-cli@^5.1.4, webpack-cli@5.x.x: version "5.1.4" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz" integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" @@ -2079,7 +2084,7 @@ webpack-cli@^5.1.4: webpack-merge@^5.7.3: version "5.9.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" + resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz" integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== dependencies: clone-deep "^4.0.1" @@ -2087,12 +2092,12 @@ webpack-merge@^5.7.3: webpack-sources@^3.2.3: version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.86.0: +webpack@^5.1.0, webpack@^5.86.0, webpack@5.x.x: version "5.88.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.1.tgz#21eba01e81bd5edff1968aea726e2fbfd557d3f8" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz" integrity sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ== dependencies: "@types/eslint-scope" "^3.7.3" @@ -2122,66 +2127,66 @@ webpack@^5.86.0: webpod@^0: version "0.0.2" - resolved "https://registry.yarnpkg.com/webpod/-/webpod-0.0.2.tgz#b577c93604fd23596488735887168b3236e3adae" + resolved "https://registry.npmjs.org/webpod/-/webpod-0.0.2.tgz" integrity sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg== which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" which@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1" + resolved "https://registry.npmjs.org/which/-/which-3.0.1.tgz" integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== dependencies: isexe "^2.0.0" wildcard@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@~8.11.0: version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== xmlhttprequest-ssl@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" + resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^2.2.2: version "2.3.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== yocto-queue@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== zx@^7.2.2: version "7.2.2" - resolved "https://registry.yarnpkg.com/zx/-/zx-7.2.2.tgz#fe1e9ba84a3806f6ea9ece39e0aea1cd7e5a4855" + resolved "https://registry.npmjs.org/zx/-/zx-7.2.2.tgz" integrity sha512-50Gjicd6ijTt7Zcz5fNX+rHrmE0uVqC+X6lYKhf2Cu8wIxDpNIzXwTmzchNdW+JY3LFsRcU43B1lHE4HBMmKgQ== dependencies: "@types/fs-extra" "^11.0.1" From 2e57f9b41af9a744fe60136dfccfb470a1ede729 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:40:56 +0100 Subject: [PATCH 10/18] fix: timer phase 'zero' should be red --- src/feedbacks.js | 2 +- tests/state.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/state.test.js diff --git a/src/feedbacks.js b/src/feedbacks.js index 2425671..881580b 100644 --- a/src/feedbacks.js +++ b/src/feedbacks.js @@ -81,7 +81,7 @@ function generateFeedbacks (instance) { options: [], callback: (_feedback) => { let { phase } = instance.state.playback_status - return phase == timerPhases.negative + return (phase == timerPhases.negative || phase == timerPhases.zero) }, }, diff --git a/tests/state.test.js b/tests/state.test.js new file mode 100644 index 0000000..f6df4d4 --- /dev/null +++ b/tests/state.test.js @@ -0,0 +1,27 @@ +import { describe, test } from 'node:test' +import { equal } from 'node:assert/strict' + +import { getTimerPhase } from '../src/state.js' + +const sec = /** @param {number} s */ s => s * 1000 +const min = /** @param {number} m */ m => sec(m) * 60 + +describe('timer phases', () => { + test('getTimerPhase - timer 1:00', () => { + const yellowSec = 15, redSec = 3 + equal( getTimerPhase(min(1), yellowSec, redSec), 'default' ) + equal( getTimerPhase(sec(15), yellowSec, redSec), 'yellow' ) + equal( getTimerPhase(sec(3), yellowSec, redSec), 'red' ) + equal( getTimerPhase(0, yellowSec, redSec), 'zero' ) + equal( getTimerPhase(min(-1), yellowSec, redSec), 'negative' ) + }) + + test('getTimerPhase - timer 3:00', () => { + const yellowSec = 60, redSec = 15 + equal( getTimerPhase(min(3), yellowSec, redSec), 'default' ) + equal( getTimerPhase(sec(60), yellowSec, redSec), 'yellow' ) + equal( getTimerPhase(sec(15), yellowSec, redSec), 'red' ) + equal( getTimerPhase(0, yellowSec, redSec), 'zero' ) + equal( getTimerPhase(min(-1), yellowSec, redSec), 'negative' ) + }) +}) From 36d5f3fd5b0f6a7aafa47625e502e77e57051301 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:04:02 +0100 Subject: [PATCH 11/18] feat: add timer appearance preset --- src/presets.js | 10 ++++++++++ src/socket.js | 3 ++- src/state.js | 26 ++++++++++++++++++++++++++ src/types.js | 2 ++ src/variables.js | 4 ++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/presets.js b/src/presets.js index 33b5473..5ee199c 100644 --- a/src/presets.js +++ b/src/presets.js @@ -264,6 +264,16 @@ function generatePresets () { getFeedbackDefaults(feedbackType.isWarningRed, { text: 'Wrap up!' }), ], }, + { + name: 'Timer appearance', + actionId: '', + style: { + size: 'auto', + text: `$(stagetimer:${variableType.currentTimerAppearance})`, + color: colors.lightBlue, + bgcolor: colors.black, + }, + }, { name: 'Timer name', actionId: '', diff --git a/src/socket.js b/src/socket.js index f359f72..70b7577 100644 --- a/src/socket.js +++ b/src/socket.js @@ -234,13 +234,14 @@ function getTimerAndUpdateState (timer_id) { instance.apiClient.send(actionIdType.get_timer, { timer_id }) .then(({ data }) => { - const { name, speaker, notes, duration, wrap_up_yellow, wrap_up_red } = /** @type {TimerData} */ (data) + const { name, speaker, notes, duration, appearance, wrap_up_yellow, wrap_up_red } = /** @type {TimerData} */ (data) updateTimerState.call(this, { name, speaker, notes, duration, + appearance, wrap_up_yellow, wrap_up_red, }) diff --git a/src/state.js b/src/state.js index 2d5f7d8..13d9ab6 100644 --- a/src/state.js +++ b/src/state.js @@ -63,6 +63,30 @@ export function getTimerPhase (timeRemaining, yellowTime = 0, redTime = 0) { return timerPhases.default } +/** + * Enum of the appearances a timer can have + * + * @readonly + * @enum {string} + */ +const timerAppearances = { + COUNTDOWN : 'COUNTDOWN', + COUNTUP : 'COUNTUP', + TOD : 'TOD', + COUNTDOWN_TOD: 'COUNTDOWN_TOD', + COUNTUP_TOD : 'COUNTUP_TOD', + HIDDEN : 'HIDDEN', +} + +// Map timer appearances to a human-friendly label +const timerAppearanceLabels = { + [timerAppearances.COUNTDOWN] : 'Countdown', + [timerAppearances.COUNTUP] : 'Count Up', + [timerAppearances.TOD] : 'Time of Day', + [timerAppearances.COUNTDOWN_TOD]: 'C/D + ToD', + [timerAppearances.COUNTUP_TOD] : 'C/U + ToD', + [timerAppearances.HIDDEN] : 'Hidden', +} /** @type {State} */ export const initialState = { @@ -88,6 +112,7 @@ export const initialState = { speaker: '', notes: '', duration: '', + appearance: '', wrap_up_yellow: 0, wrap_up_red: 0, }, @@ -206,6 +231,7 @@ export function updateTimerState (newState) { [variableType.currentTimerNotes]: updatedState.notes, [variableType.currentTimerSpeaker]: updatedState.speaker, [variableType.currentTimerDuration]: updatedState.duration, + [variableType.currentTimerAppearance]: timerAppearanceLabels[updatedState.appearance], }) instance.checkFeedbacks( diff --git a/src/types.js b/src/types.js index 8ace032..7f46b7a 100644 --- a/src/types.js +++ b/src/types.js @@ -89,6 +89,7 @@ * @property {string} speaker * @property {string} notes * @property {string} duration + * @property {string} appearance * @property {number} wrap_up_yellow * @property {number} wrap_up_red */ @@ -149,6 +150,7 @@ * @property {string} notes * @property {string} speaker * @property {string} duration + * @property {string} appearance * @property {number} wrap_up_yellow * @property {number} wrap_up_red */ diff --git a/src/variables.js b/src/variables.js index bc14875..6d28e8c 100644 --- a/src/variables.js +++ b/src/variables.js @@ -16,6 +16,8 @@ export const variableType = { currentTimerDuration: 'currentTimerDuration', currentTimerDurationAsMs: 'currentTimerDurationAsMs', + currentTimerAppearance: 'currentTimerAppearance', + currentTimerRemaining: 'currentTimerRemaining', currentTimerRemainingAsMs: 'currentTimerRemainingAsMs', currentTimerRemainingHours: 'currentTimerRemainingHours', @@ -36,6 +38,8 @@ const variables = [ { variableId: variableType.currentTimerDuration, name: 'Timer duration' }, { variableId: variableType.currentTimerDurationAsMs, name: 'Timer duration (ms)' }, + { variableId: variableType.currentTimerAppearance, name: 'Timer appearance' }, + { variableId: variableType.currentTimerRemaining, name: 'Timer remaining time' }, { variableId: variableType.currentTimerRemainingAsMs, name: 'Timer remaining time (ms)' }, { variableId: variableType.currentTimerRemainingHours, name: 'Timer remaining time (hours)' }, From 769c10fca39208761cc7fbd6809840893d871d51 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:20:09 +0100 Subject: [PATCH 12/18] feat: add room timezone preset (experimental) --- src/presets.js | 10 ++++++++++ src/socket.js | 6 ++++-- src/state.js | 2 ++ src/types.js | 2 ++ src/variables.js | 2 ++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/presets.js b/src/presets.js index 5ee199c..10eec7a 100644 --- a/src/presets.js +++ b/src/presets.js @@ -294,6 +294,16 @@ function generatePresets () { bgcolor: colors.black, }, }, + { + name: 'Timezone', + actionId: '', + style: { + size: 'auto', + text: `$(stagetimer:${variableType.roomTimezone})`, + color: colors.lightGray, + bgcolor: colors.black, + }, + }, { name: 'Start flashing', actionId: actionIdType.start_flashing, diff --git a/src/socket.js b/src/socket.js index 70b7577..dd97e04 100644 --- a/src/socket.js +++ b/src/socket.js @@ -85,13 +85,14 @@ export function socketStart (instance) { instance.apiClient.send(actionIdType.get_room, {}) .then(({ data }) => { - const { _id, name, blackout, focus_message } = /** @type {RoomData} */(data) + const { _id, name, blackout, focus_message, timezone } = /** @type {RoomData} */(data) updateRoomState.call(instance, { roomId: _id, roomName: name, roomBlackout: blackout, roomFocus: focus_message, + roomTimezone: timezone, }) }) .catch((error) => { @@ -183,11 +184,12 @@ export function socketStart (instance) { socket.on(stagetimerEvents.room, (payload) => { instance.log('debug', 'Event: room') - const { blackout, focus_message } = payload + const { blackout, focus_message, timezone } = payload updateRoomState.call(instance, { roomBlackout: blackout, roomFocus: focus_message, + roomTimezone: timezone, }) }) diff --git a/src/state.js b/src/state.js index 13d9ab6..5e4560d 100644 --- a/src/state.js +++ b/src/state.js @@ -95,6 +95,7 @@ export const initialState = { roomName: undefined, roomBlackout: false, roomFocus: false, + roomTimezone: '', }, viewer: { isFlashing: false, @@ -144,6 +145,7 @@ export function updateRoomState (newState) { instance.setVariableValues({ [variableType.roomId]: updatedState.roomId, [variableType.roomName]: updatedState.roomName, + [variableType.roomTimezone]: updatedState.roomTimezone ?? 'Auto', }) instance.checkFeedbacks( diff --git a/src/types.js b/src/types.js index 7f46b7a..361ebed 100644 --- a/src/types.js +++ b/src/types.js @@ -76,6 +76,7 @@ * @property {boolean} blackout * @property {boolean} focus_message * @property {string} logo + * @property {string} timezone */ /** @@ -111,6 +112,7 @@ * @property {string} [roomName] * @property {boolean} roomBlackout * @property {boolean} roomFocus + * @property {string} roomTimezone */ /** diff --git a/src/variables.js b/src/variables.js index 6d28e8c..2619a60 100644 --- a/src/variables.js +++ b/src/variables.js @@ -7,6 +7,7 @@ export const variableType = { roomId: 'roomId', roomName: 'roomName', + roomTimezone: 'roomTimezone', currentTimerId: 'currentTimerId', currentTimerName: 'currentTimerName', @@ -29,6 +30,7 @@ export const variableType = { const variables = [ { variableId: variableType.roomId, name: 'Room ID' }, { variableId: variableType.roomName, name: 'Room name' }, + { variableId: variableType.roomTimezone, name: 'Room timezone' }, { variableId: variableType.currentTimerId, name: 'Timer ID' }, { variableId: variableType.currentTimerName, name: 'Timer name' }, From b6c7247de38560f1eaeb8e3b51151dc85073fe11 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:46:20 +0100 Subject: [PATCH 13/18] feat: add Create Timer action and preset --- src/actions.js | 153 ++++++++++++++++++++++++++++++++++++++++---- src/assets.js | 3 +- src/config.js | 74 +++++++++++++++++++++ src/presets.js | 41 ++++++++++-- src/state.js | 28 +------- src/types.js | 1 + src/utils.js | 15 +++++ tests/state.test.js | 20 ++++++ 8 files changed, 291 insertions(+), 44 deletions(-) diff --git a/src/actions.js b/src/actions.js index c012fbb..730b5e3 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,3 +1,5 @@ +import { messageColorDropdownOptions, timerAppearanceDropdownOptions, timerAppearances, timerTriggers, timerTriggersDropdownOptions, timerTypes, timerTypesDropdownOptions } from './config.js' + /** * Enum of Action IDs allowed by Stagetimer.io API (v1) * @@ -35,6 +37,7 @@ export const actionIdType = { start_or_stop_timer: 'start_or_stop_timer', reset_timer: 'reset_timer', get_timer: 'get_timer', + create_timer: 'create_timer', // Message show_or_hide_message: 'show_or_hide_message', @@ -96,16 +99,142 @@ const actionOptions = { tooltip: 'The ID of the timer you want to target.', }, ], + timerCreate: [ + { + id: 'name', + type: 'textinput', + label: 'Name', + tooltip: 'Name of the timer.', + }, + { + id: 'speaker', + type: 'textinput', + label: 'Speaker', + tooltip: 'Used to identify speakers.', + }, + { + id: 'notes', + type: 'textinput', + label: 'Notes', + tooltip: 'Notes related to the timer or speaker.', + }, + { + id: 'hours', + type: 'number', + label: 'Hours', + default: 0, + required: false, + min: 0, + max: 999, + tooltip: 'Duration (hours).', + }, + { + id: 'minutes', + type: 'number', + label: 'Minutes', + default: 10, + required: false, + min: 0, + max: 59, + tooltip: 'Duration (minutes).', + }, + { + id: 'seconds', + type: 'number', + label: 'Seconds', + default: 0, + required: false, + min: 0, + max: 59, + tooltip: 'Duration (seconds).', + }, + { + id: 'wrap_up_yellow', + type: 'number', + label: 'Wrap up, yellow', + default: 60, + required: false, + min: 0, + max: 9999, + tooltip: 'Yellow wrap-up time (in seconds from the end).', + }, + { + id: 'wrap_up_red', + type: 'number', + label: 'Wrap up, red', + default: 15, + required: false, + min: 0, + max: 9999, + tooltip: 'Red wrap-up time (in seconds from the end).', + }, + { + id: 'advanced', + type: 'static-text', + label: 'Advanced options:', + value: 'The settings below are for advanced timer configuration.', + }, + { + id: 'appearance', + type: 'dropdown', + label: 'Timer appearance', + tooltip: `Defines how the timer is displayed. See the "Timer Appearances" page in the docs. Default: ${timerAppearances.COUNTDOWN}`, + choices: timerAppearanceDropdownOptions, + default: 0, + }, + { + id: 'type', + type: 'dropdown', + label: 'Timer type', + tooltip: `Defines the type of timer, ie. how runtime length is handled. See the "Timer Types" page in the docs. Default: ${timerTypes.DURATION}`, + choices: timerTypesDropdownOptions, + default: 0, + }, + { + id: 'trigger', + type: 'dropdown', + label: 'Timer trigger', + tooltip: `Defines how the timer is triggered (started). See the "Timer Triggers" page in the docs. Default: ${timerTriggers.MANUAL}`, + choices: timerTriggersDropdownOptions, + default: 0, + }, + { + id: 'start_time', + type: 'textinput', + label: 'Start time', + tooltip: 'Set a hard start time for this cue. Required when `trigger=LINKED` and `trigger=SCHEDULED`, but optional for `trigger=MANUAL`', + }, + { + id: 'start_time_uses_date', + type: 'checkbox', + label: 'Start time uses date', + default: false, + tooltip: 'Determines if the date-part of `start_time` is being used. If `true`, then the the full date is used (e.g. 11 am on Oct 6). But if `false`, the start date is interpreted as today and the date part ignored (e.g. 11 am today).', + }, + { + id: 'finish_time', + type: 'textinput', + label: 'Finish time', + tooltip: 'Finish time for the cue. Required when `type=FINISH_TIME`, otherwise ignored.', + }, + { + id: 'finish_time_uses_date', + type: 'checkbox', + label: 'Finish time uses date', + default: false, + tooltip: 'Determines if the date-part of `finish_time` is being used. If `true`, then the the full date is used (e.g. 11 am on Oct 6). But if `false`, the start date is interpreted as today and the date part ignored (e.g. 11 am today).', + }, + ], message: [ { id: 'index', type: 'number', label: 'Message index', - default: 0, // According to Companion docs, `default: ""` should work for optional, but is of course a type error. 0 seems to work the same but without errors. - required: false, + // @ts-expect-error: According to Companion docs, `default: ''` should work for optional, but is of course a type error. + default: '', min: 1, max: 99, - tooltip: 'Index of a message to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second message from the top, set `index=2`. To target the active/first message, clear the input field.', + tooltip: 'Index of a message to target in a room. Note: Index is not zero-based, it starts at 1. Example: To target the second message from the top, set `index=2`. Leave blank to target active or first message.', }, { id: 'message_id', @@ -119,19 +248,15 @@ const actionOptions = { id: 'text', type: 'textinput', label: 'Message text', - tooltip: 'Write the text content of the message.', + tooltip: 'Text content of the message.', }, { id: 'color', type: 'dropdown', label: 'Text color', - tooltip: 'Choose a text color for the message, default color is white.', - choices: [ - { id: 'white', label: 'White' }, - { id: 'green', label: 'Green' }, - { id: 'red', label: 'Red' }, - ], - default: 'white', + tooltip: 'Choose a text color for the message. Default: white', + choices: messageColorDropdownOptions, + default: 0, }, { id: 'bold', @@ -281,6 +406,12 @@ export function loadActions (instance) { options: actionOptions.timer, callback: actionCallback, }, + [actionIdType.create_timer]: { + name: 'Timer: Create new timer', + description: 'Creates a new timer in the room', + options: actionOptions.timerCreate, + callback: actionCallback, + }, // Message actions [actionIdType.show_message]: { diff --git a/src/assets.js b/src/assets.js index 0a5e077..17dd9fa 100644 --- a/src/assets.js +++ b/src/assets.js @@ -32,9 +32,10 @@ export const icons = { timer: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMAECBAUGBwf4CQn6Cwv8DP0N/vGoQcGAAAARFJREFUWMPtlstuhDAMRZ2Ex4SZTBqf///XLkIZKEiVTHbNXUUgH2xzsRHp6mqmETTF0Ar3AIAyNsNpBfpGuEXCE9DBThn8HifiC2Dmef2pbcXVqq31FphWcAiuniIkszvy+WqC0ZqcFxnzsTgPxUILtV+u/HLbCyx+jmtYgMUdHxMNuAT1MB3d6/SqpX/qE5WA+XMjowYcvDf/Acmd0jbiZIDNglbcvkUReNwrdh/lXrz9RdoGo1z4MdptfNLTZmNRuBge1o9MpsvhYR4Bkg/urZqtyVX7zieaeXzKCKRdtE93hrvIoMCyvsi6em7tRl8ANKWUFSDfXYxjYZNODZZsiG8F/Wr3U9HV1dXV1fVP9A0dvxCm3WkvCAAAAABJRU5ErkJggg==', timerOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+Aj5CfoK+wv8DP0N/vTWO0pgAAATdJREFUWMPtlstuwzAMBClFcR5yUsUV5/8/tQe1sewEKLJn7c0GNOZS5MJmQ0O6Qq1xfZrAS0467gp1PX4BgDqpuApw7nDegFHDxQJwj0/cbOkG+FGs79JVc4HZzGIFVN6xApw6XHMt+m3FcA1mMaXQ3mUo8v3m1/YXkO/XTgC1b1eEqpAOx9XwuXv/BUkyejYzi3eAshpOkAVcgX5iDs/1cxYBt55KW8MLLuDg8Wz/AjCHXdkqbrsiGm7boskBn3Szu1PrxGzK/mQjNvMVbgBLFAcl/a39roFFG2Nz2IXHobYMVfe1vA3VokXUsl3Wl4n5NO/8Da8L1U817ZyFLlSlfHdg/r3IdPuFZNlwK8VLKYsD3LtQle5jasMBgJ+6r2TTlPLDwb/7n4pYaxh/XkNDQ0NDQ//pB1yLGkgS62hVAAAAAElFTkSuQmCC', timerReset: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAARVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////9SnXPCAAAAFnRSTlMAECAwQFBgcH+AkJ+gr7C/wM/Q3+Dvlll16gAAAT1JREFUWMPtll1vwyAMRS+U0nx0I4z6/P+fuofQrlorTXLyttwnhOQTXzB2pEOHdlMGK1PaCzcCQMu74WwFxp1ws9IVsLOfco7POCk2wM2LdvfWcatrr98Glw5OKayrCYq7OurrboHsTe6NrwjNQ0v38/qlT/DU89TD8keZoxSGWnL/zOTAFZCkATOKVLH1ZoK9O9I/1aOMGIyUaCFhQVLFHDhYJCWaNDGOTNKN00/aftzIfGWUbiQ3bjV7z25as0tus2tUgKBCzhRFCI+0nYVSqFdaDMZcmf2F0ss4LtBO0qnBEiVdfWUs648s9KcWw5ZHpsvb5uFuAaow/N4bvMlJ0V54w4b2qQyUp+hYtjR36WzA3C9yHT2bZmNsAFZKqQZQtw7G3HjILjsM2TQtBva130/FoUOHDh069E/0DUb+Fu6sLuw3AAAAAElFTkSuQmCC', + timerCreate: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA8UExURQAAAP///////////////////////////////////////////////////////////////////////////9hJaBMAAAATdFJOUwAQIEBQYHB/gJCfoLC/wM/Q3+8ahBwYAAABDklEQVRYw+2Wy27EIAxFDeRRkjIpPv//r10kJLSTqhpA6qLclRXJR75g7Ih0dTXTCBq8a4V7A4A4NsPpDrSNcIu4FdChnDLYHCdiI1DMs5q8HbjddanfCNMBds7skYdQ3B3b89cAY2lxp6/Fm3QCEEtoLp3XHp89/J7FL8hnae5r7AtwAeQOZ/TuSH9VyjLOuQkm5w7ihhbg4JFMJy1PZb+OWy+cr8DdmDUVZvOs/CrOsv+0UX5q47WsjUWvR2b8WvvIZLodHsUjQDaYv3+bS4sTsfrEmyvGp4xAyLJtqBnuIoMCy3GR++qp2o02AmgIYVOArXYxjvF6szo1WLLOPxT0o91PRVdXV1dX1z/RJ1OeEd1SZ8kDAAAAAElFTkSuQmCC', // Message message: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6BAMAAADsN3L5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAALVBMVEUAAAD///////////////////////////////////////////////////////+hSKubAAAADnRSTlMAECAwQGBwkKC/wM/f7/7VrqgAAABrSURBVEjHY2AYBYRBzjsE2IpbGes7ZJCAUx03iroDONXxoah7MKpuVN2gVMeJom4BTnXM95CUvVXAnZE0Vq1aDVTyZhUQFOHPmixAdYVEZGGguqsMRKl7rUCcukKiig7mq6PF5ygYBUMEAACZJi4Vt/I3cwAAAABJRU5ErkJggg==', messageOff: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMAECAwQFBgcH+Aj5CfoK+/wM/f702OQ14AAADcSURBVFjD7dbRDoIwDAXQu6JDRWTr+v/f6gOaMBEIXR97P+AkbZq7AR6POoGZ0LP8TY5nuYcID7KZ/iTHshs+ydGBd3p7gy2H3pbbHVhzLfQy5YC7LYcLm3E3AKBsxclEmwNrOOEOAGIx4kRuGxej5OQZAITRihP+u0A1JyUCQMdG3HeBkxUneTVwEyd8AYArt3DVdPXFJAXXVef7JABhLtVCqoIaU0op5eXF9Kqnp2qVmRvColQfjVyJdakytXCZfkuVG7jPoMtSHbRcV+L6VeLgPy+Px+PxeA7zBmxuLz3gMRqIAAAAAElFTkSuQmCC', - messageNew: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA2UExURQAAAP////////////////////////////////////////////////////////////////////FjxvwAAAARdFJOUwAQIDBAYHB/gI+QoL/Az9/vODCOcwAAAJVJREFUWMPt1dsKhCAUheGlox2cPPT+LzvUFDSRENsNwbD+qxL8QBQ2wFhbXZ4vS16i+blaJ+BSncsC7rh/AMLxv5FzgCP3MBfckgHM+jE0cvdWn+L638OOfCj/xY1Ar8idE3BTXYsC7lVqWrGS2WPfcWmfGTluBZG2t11pMDrjduWKB/S4ZKHIaR30e8MejDHGGJP0AY9hJJdzc693AAAAAElFTkSuQmCC', + messageCreate: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAA6CAMAAAApx5/4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAA2UExURQAAAP////////////////////////////////////////////////////////////////////FjxvwAAAARdFJOUwAQIDBAYHB/gI+QoL/Az9/vODCOcwAAAJVJREFUWMPt1dsKhCAUheGlox2cPPT+LzvUFDSRENsNwbD+qxL8QBQ2wFhbXZ4vS16i+blaJ+BSncsC7rh/AMLxv5FzgCP3MBfckgHM+jE0cvdWn+L638OOfCj/xY1Ar8idE3BTXYsC7lVqWrGS2WPfcWmfGTluBZG2t11pMDrjduWKB/S4ZKHIaR30e8MejDHGGJP0AY9hJJdzc693AAAAAElFTkSuQmCC', } diff --git a/src/config.js b/src/config.js index 01b2993..29ebe20 100644 --- a/src/config.js +++ b/src/config.js @@ -1,3 +1,5 @@ +import { createDropdownOptions } from './utils.js' + // Regular Expressions for validation const roomIdRegExp = /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZ]{8}$/ const apiKeyRegExp = /^[a-f0-9-]{32}$/ @@ -72,3 +74,75 @@ export const configFields = [ default: 'https://api.stagetimer.io/v1/', }, ] + + +/** + * Enum of valid message colors + * + * @readonly + * @enum {string} + */ +export const messageColors = { + white: 'white', + green: 'green', + red: 'red', +} + +export const messageColorDropdownOptions = createDropdownOptions(messageColors) + +/** + * Enum of valid timer appearances + * + * @readonly + * @enum {string} + */ +export const timerAppearances = { + COUNTDOWN : 'COUNTDOWN', + COUNTUP : 'COUNTUP', + TOD : 'TOD', + COUNTDOWN_TOD: 'COUNTDOWN_TOD', + COUNTUP_TOD : 'COUNTUP_TOD', + HIDDEN : 'HIDDEN', +} + +/** + * Map timer appearances to a human-friendly label + */ +export const timerAppearancesLabels = { + [timerAppearances.COUNTDOWN] : 'Countdown', + [timerAppearances.COUNTUP] : 'Count Up', + [timerAppearances.TOD] : 'Time of Day', + [timerAppearances.COUNTDOWN_TOD]: 'C/D + ToD', + [timerAppearances.COUNTUP_TOD] : 'C/U + ToD', + [timerAppearances.HIDDEN] : 'Hidden', +} + + +export const timerAppearanceDropdownOptions = createDropdownOptions(timerAppearancesLabels) + +/** + * Enum of valid timer types + * + * @readonly + * @enum {string} + */ +export const timerTypes = { + DURATION: 'DURATION', + FINISH_TIME: 'FINISH_TIME', +} + +export const timerTypesDropdownOptions = createDropdownOptions(timerTypes) + +/** + * Enum of valid timer trigger + * + * @readonly + * @enum {string} + */ +export const timerTriggers = { + MANUAL: 'MANUAL', + LINKED: 'LINKED', + SCHEDULED: 'SCHEDULED', +} + +export const timerTriggersDropdownOptions = createDropdownOptions(timerTriggers) diff --git a/src/presets.js b/src/presets.js index 10eec7a..384517f 100644 --- a/src/presets.js +++ b/src/presets.js @@ -425,13 +425,39 @@ function generatePresets () { }, feedbacks: [], }, + { + name: 'Create timer', + actionId: actionIdType.create_timer, + actionOptions: { + hours: 0, + minutes: 10, + seconds: 0, + wrap_up_yellow: 60, + wrap_up_red: 15, + appearance: 0, + type: 0, + trigger: 0, + }, + style: { + size: '14', + text: 'Create', + alignment: 'center:bottom', + png64: icons.timerCreate, + pngalignment: 'center:top', + color: colors.white, + bgcolor: colors.black, + }, + feedbacks: [], + }, ], 'Message': [ { name: 'Show/hide message', actionId: actionIdType.show_or_hide_message, - actionOptions: {}, + actionOptions: { + index: '', + }, style: { size: '14', text: 'Toggle', @@ -450,7 +476,9 @@ function generatePresets () { { name: 'Show message', actionId: actionIdType.show_message, - actionOptions: {}, + actionOptions: { + index: '', + }, style: { size: '14', text: 'Show', @@ -465,7 +493,9 @@ function generatePresets () { { name: 'Hide message', actionId: actionIdType.hide_message, - actionOptions: {}, + actionOptions: { + index: '', + }, style: { size: '14', text: 'Hide', @@ -481,14 +511,13 @@ function generatePresets () { name: 'Create message', actionId: actionIdType.create_message, actionOptions: { - text: 'New message', - color: 'white', + color: 0, }, style: { size: '14', text: 'Create', alignment: 'center:bottom', - png64: icons.messageNew, + png64: icons.messageCreate, pngalignment: 'center:top', color: colors.white, bgcolor: colors.black, diff --git a/src/state.js b/src/state.js index 5e4560d..c151e86 100644 --- a/src/state.js +++ b/src/state.js @@ -1,6 +1,7 @@ import { feedbackType } from './feedbacks.js' import { createTimeset } from './utils.js' import { variableType } from './variables.js' +import { timerAppearancesLabels } from './config.js' // // Timekeeper service @@ -63,31 +64,6 @@ export function getTimerPhase (timeRemaining, yellowTime = 0, redTime = 0) { return timerPhases.default } -/** - * Enum of the appearances a timer can have - * - * @readonly - * @enum {string} - */ -const timerAppearances = { - COUNTDOWN : 'COUNTDOWN', - COUNTUP : 'COUNTUP', - TOD : 'TOD', - COUNTDOWN_TOD: 'COUNTDOWN_TOD', - COUNTUP_TOD : 'COUNTUP_TOD', - HIDDEN : 'HIDDEN', -} - -// Map timer appearances to a human-friendly label -const timerAppearanceLabels = { - [timerAppearances.COUNTDOWN] : 'Countdown', - [timerAppearances.COUNTUP] : 'Count Up', - [timerAppearances.TOD] : 'Time of Day', - [timerAppearances.COUNTDOWN_TOD]: 'C/D + ToD', - [timerAppearances.COUNTUP_TOD] : 'C/U + ToD', - [timerAppearances.HIDDEN] : 'Hidden', -} - /** @type {State} */ export const initialState = { room: { @@ -233,7 +209,7 @@ export function updateTimerState (newState) { [variableType.currentTimerNotes]: updatedState.notes, [variableType.currentTimerSpeaker]: updatedState.speaker, [variableType.currentTimerDuration]: updatedState.duration, - [variableType.currentTimerAppearance]: timerAppearanceLabels[updatedState.appearance], + [variableType.currentTimerAppearance]: timerAppearancesLabels[updatedState.appearance], }) instance.checkFeedbacks( diff --git a/src/types.js b/src/types.js index 361ebed..604cc46 100644 --- a/src/types.js +++ b/src/types.js @@ -7,6 +7,7 @@ /** @typedef {import('@companion-module/base').CompanionActionDefinitions} CompanionActionDefinitions */ /** @typedef {import('@companion-module/base').CompanionActionEvent} CompanionActionEvent */ +/** @typedef {import('@companion-module/base').DropdownChoice[]} CompanionDropdownOptions */ /** @typedef {import('@companion-module/base').CompanionButtonStepActions} CompanionButtonStepActions */ /** @typedef {import('@companion-module/base').SomeCompanionActionInputField} SomeCompanionActionInputField */ diff --git a/src/utils.js b/src/utils.js index 785ce09..b790433 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,18 @@ +/** + * Converts an enum object to an array of objects for creating Companion action dropdowns. + * + * @param {Object.} enumObj + * @returns {CompanionDropdownOptions} + */ +export function createDropdownOptions (enumObj) { + const optionsList = Object.entries(enumObj).map(([key, val]) => ({ id: key, label: val })) + + return [ + { id: 0, label: '(Default)' }, + ...optionsList, + ] +} + /** * Pad with zeroes * diff --git a/tests/state.test.js b/tests/state.test.js index f6df4d4..036d9d8 100644 --- a/tests/state.test.js +++ b/tests/state.test.js @@ -2,6 +2,9 @@ import { describe, test } from 'node:test' import { equal } from 'node:assert/strict' import { getTimerPhase } from '../src/state.js' +import { deepEqual } from 'node:assert' +import { createDropdownOptions } from '../src/utils.js' +import { timerTriggers } from '../src/config.js' const sec = /** @param {number} s */ s => s * 1000 const min = /** @param {number} m */ m => sec(m) * 60 @@ -25,3 +28,20 @@ describe('timer phases', () => { equal( getTimerPhase(min(-1), yellowSec, redSec), 'negative' ) }) }) + +describe('enums', () => { + + test('create action dropdown options from triggers enum', () => { + + deepEqual( + createDropdownOptions(timerTriggers), + [ + { id: 0, label: '(Default)' }, + { id: 'MANUAL', label: 'MANUAL' }, + { id: 'LINKED', label: 'LINKED' }, + { id: 'SCHEDULED', label: 'SCHEDULED' }, + ], + ) + }) + +}) From 344d03249d91a6a90e5bf5a007505855996c3ce2 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:59:52 +0100 Subject: [PATCH 14/18] chore: remove and update dependencies --- package.json | 3 +- yarn.lock | 151 ++++++++++++++++++++------------------------------- 2 files changed, 59 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 023ac29..37046f5 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "url": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git" }, "dependencies": { - "@companion-module/base": "~1.4.1", - "date-fns": "^2.30.0", + "@companion-module/base": "~1.6.0", "socket.io-client": "^4.7.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 3c4c166..82ec440 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,28 +7,22 @@ resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@babel/runtime@^7.21.0": - version "7.22.6" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz" - integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== +"@companion-module/base@^1.4.1", "@companion-module/base@~1.6.0": + version "1.6.0" + resolved "https://registry.npmjs.org/@companion-module/base/-/base-1.6.0.tgz" + integrity sha512-KnsgHtgmB36t2wlBSYyRgw4eSrm6rJXoBWClBURfssk9OgochaJtWwPLuA/SgjLAxPOnTTNt4PvHgzcVv6MjYg== dependencies: - regenerator-runtime "^0.13.11" - -"@companion-module/base@^1.4.1", "@companion-module/base@~1.4.1": - version "1.4.1" - resolved "https://registry.npmjs.org/@companion-module/base/-/base-1.4.1.tgz" - integrity sha512-xg5OX33ptfFsV/drfeNTHID7hp9f2cdp8V+7Pj8uartdNstCr28W3bAy8xRz+XRFKxQVkJcL2LqrkYZ8GGfetw== - dependencies: - "@sentry/node" "^7.36.0" - "@sentry/tracing" "^7.36.0" + "@sentry/node" "^7.63.0" + "@sentry/tracing" "^7.63.0" ajv "^8.12.0" - debounce-fn "github:julusian/debounce-fn#4.0.0-maxWaithack.0" + colord "^2.9.3" ejson "^2.2.3" eventemitter3 "^4.0.7" + mimic-fn "^3.0.0" nanoid "^3.3.4" p-queue "^6.6.2" p-timeout "^4.1.0" - tslib "^2.5.0" + tslib "^2.6.1" "@companion-module/tools@^1.3.2": version "1.3.2" @@ -171,58 +165,52 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@sentry-internal/tracing@7.57.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.57.0.tgz" - integrity sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A== - dependencies: - "@sentry/core" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" - tslib "^2.4.1 || ^1.9.3" - -"@sentry/core@7.57.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz" - integrity sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw== - dependencies: - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" - tslib "^2.4.1 || ^1.9.3" - -"@sentry/node@^7.36.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry/node/-/node-7.57.0.tgz" - integrity sha512-63mjyUVM6sfJFVQ5TGVRVGUsoEfESl5ABzIW1W0s9gUiQPaG8SOdaQJglb2VNrkMYxnRHgD8Q9LUh/qcmUyPGw== - dependencies: - "@sentry-internal/tracing" "7.57.0" - "@sentry/core" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" - cookie "^0.4.1" +"@sentry-internal/tracing@7.80.1": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.80.1.tgz" + integrity sha512-5gZ4LPIj2vpQl2/dHBM4uXMi9OI5E0VlOhJQt0foiuN6JJeiOjdpJFcfVqJk69wrc0deVENTtgKKktxqMwVeWQ== + dependencies: + "@sentry/core" "7.80.1" + "@sentry/types" "7.80.1" + "@sentry/utils" "7.80.1" + +"@sentry/core@7.80.1": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry/core/-/core-7.80.1.tgz" + integrity sha512-3Yh+O9Q86MxwIuJFYtuSSoUCpdx99P1xDAqL0FIPTJ+ekaVMiUJq9NmyaNh9uN2myPSmxvEXW6q3z37zta9ZHg== + dependencies: + "@sentry/types" "7.80.1" + "@sentry/utils" "7.80.1" + +"@sentry/node@^7.63.0": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry/node/-/node-7.80.1.tgz" + integrity sha512-0NWfcZMlyQphKWsvyzfhGm2dCBk5DUPqOGW/vGx18G4tCCYtFcAIj/mCp/4XOEcZRPQgb9vkm+sidGD6DnwWlA== + dependencies: + "@sentry-internal/tracing" "7.80.1" + "@sentry/core" "7.80.1" + "@sentry/types" "7.80.1" + "@sentry/utils" "7.80.1" https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^2.4.1 || ^1.9.3" -"@sentry/tracing@^7.36.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.57.0.tgz" - integrity sha512-D8eKJMYN529mDP9lsOLyhe0Rf9Qiexo7Ul4+MQwDlwRr9c9tc0AdGwFlnKGvCMDh7ucITzvZkMZDHBapU3WHNQ== +"@sentry/tracing@^7.63.0": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.80.1.tgz" + integrity sha512-sFkcxCBtLNVa3EyeCafZqhJHZ714f2+ryPWTBckAmxAsON4yjh/YLs2X1FJ2n6Rnv16TP6gWGt4SnhFT03WStA== dependencies: - "@sentry-internal/tracing" "7.57.0" + "@sentry-internal/tracing" "7.80.1" -"@sentry/types@7.57.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz" - integrity sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w== +"@sentry/types@7.80.1": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry/types/-/types-7.80.1.tgz" + integrity sha512-CVu4uPVTOI3U9kYiOdA085R7jX5H1oVODbs9y+A8opJ0dtJTMueCXgZyE8oXQ0NjGVs6HEeaLkOuiV0mj8X3yw== -"@sentry/utils@7.57.0": - version "7.57.0" - resolved "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz" - integrity sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg== +"@sentry/utils@7.80.1": + version "7.80.1" + resolved "https://registry.npmjs.org/@sentry/utils/-/utils-7.80.1.tgz" + integrity sha512-bfFm2e/nEn+b9++QwjNEYCbS7EqmteT8uf0XUs7PljusSimIqqxDtK1pfD9zjynPgC8kW/fVBKv0pe2LufomeA== dependencies: - "@sentry/types" "7.57.0" - tslib "^2.4.1 || ^1.9.3" + "@sentry/types" "7.80.1" "@socket.io/component-emitter@~3.1.0": version "3.1.0" @@ -700,6 +688,11 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colord@^2.9.3: + version "2.9.3" + resolved "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== + colorette@^2.0.14: version "2.0.20" resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" @@ -720,11 +713,6 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -739,19 +727,6 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== -date-fns@^2.30.0: - version "2.30.0" - resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz" - integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== - dependencies: - "@babel/runtime" "^7.21.0" - -"debounce-fn@github:julusian/debounce-fn#4.0.0-maxWaithack.0": - version "4.0.0-maxWaithack.0" - resolved "git+ssh://git@github.com/julusian/debounce-fn.git#3ca54d1526c19f541fe6f103abbceda31554caa9" - dependencies: - mimic-fn "^3.0.0" - debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" @@ -1413,11 +1388,6 @@ lodash.merge@^4.6.2: resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" @@ -1753,11 +1723,6 @@ rechoir@^0.8.0: dependencies: resolve "^1.20.0" -regenerator-runtime@^0.13.11: - version "0.13.11" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" @@ -2001,10 +1966,10 @@ tslib@^1.8.1: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -"tslib@^2.4.1 || ^1.9.3", tslib@^2.5.0: - version "2.6.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz" - integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== +tslib@^2.6.1: + version "2.6.2" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== tsutils@^3.21.0: version "3.21.0" From 52726fe02b023a43ff605c1c530048559042817c Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:16:43 +0100 Subject: [PATCH 15/18] refactor: Reformat HELP doc --- companion/HELP.md | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/companion/HELP.md b/companion/HELP.md index d15bb09..eadbcf8 100644 --- a/companion/HELP.md +++ b/companion/HELP.md @@ -6,6 +6,8 @@ This module lets you remotely control [Stagetimer](https://stagetimer.io/) using It connects using the [Stagetimer HTTP RPC API](https://stagetimer.io/docs/api-v1) and [Stagetimer Socket.io endpoint](https://stagetimer.io/docs/api-v1/#socket-io-endpoint). +--- + ## Requirements To use this module you need: @@ -14,26 +16,37 @@ To use this module you need: - **Room ID**: The ID of the Stagetimer room you want to control. - **API Key**: A key that authorizes you to use the Stagetimer API. You can generate an API key on the controller page. +--- + ## Configuration 1. Click on the module in the Connections list to reveal the configuration pane. 2. Enter your **Room ID** and **API Key** in the form and click *Save*. 3. If the details you entered are correct, the module will connect. If the module fails to connect, please review the output in the Companion Logs tab. +--- + ## Presets There are multiple presets available for the most common actions, ready to drop into your button layout. +--- + ## Actions The following Actions are available: +**Message actions:** + - **Message: Hide** - Hide a message in the room + Hide a message in the room - **Message: Show** - Show a message in the room + Show a message in the room - **Message: Toggle visibility** - Show/hide a message in the room + Show/hide a message in the room + +**Timer actions:** + - **Timer: Reset** Reset a specific timer to original duration - **Timer: Start** @@ -42,6 +55,9 @@ The following Actions are available: Stop a specific timer in the room - **Timer: Toggle playback** Toggle (start/stop) a specific timer in the room + +**Transport actions:** + - **Transport: Add time** Add an amount of time to the highlighted timer in the room. - **Transport: Next** @@ -56,12 +72,9 @@ The following Actions are available: Stop the highlighted timer in the room - **Transport: Subtract time** Subtract an amount of time from the highlighted timer in the room. -- **Utility: Get room** - Get status of the room -- **Utility: Get status** - Get playback status of the room -- **Utility: Test auth** - Test connection and authentication + +**Viewer actions:** + - **Viewer: Disable blackout mode** Disable blackout mode in the room - **Viewer: Disable focus mode** @@ -79,6 +92,17 @@ The following Actions are available: - **Viewer: Toggle focus mode** Toggle (enable/disable) focus mode in the room +**Utility actions:** + +- **Utility: Get room** + Get status of the room +- **Utility: Get status** + Get playback status of the room +- **Utility: Test auth** + Test connection and authentication + +--- + ## Variables - `$(stagetimer:currentTimerDuration)` - Timer duration @@ -92,6 +116,8 @@ The following Actions are available: - `$(stagetimer:roomId)` - Room ID - `$(stagetimer:roomName)` - Room name +--- + ## Feedbacks - Blackout mode From f35441f7b80b72029241209cf25563f211638385 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:25:20 +0100 Subject: [PATCH 16/18] chore: update HELP doc with new actions and variables --- companion/HELP.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/companion/HELP.md b/companion/HELP.md index eadbcf8..831161b 100644 --- a/companion/HELP.md +++ b/companion/HELP.md @@ -30,6 +30,9 @@ To use this module you need: There are multiple presets available for the most common actions, ready to drop into your button layout. +Find a complete list in the **Presets** section of this guide in the Stagetimer docs: + **[Controlling Stagetimer via Companion for Stream Deck (Comprehensive Guide)](https://stagetimer.io/docs/integration-with-streamdeck-companion/#presets)** + --- ## Actions @@ -44,6 +47,8 @@ The following Actions are available: Show a message in the room - **Message: Toggle visibility** Show/hide a message in the room +- **Message: Create new message** + Create a new message in the room **Timer actions:** @@ -55,6 +60,8 @@ The following Actions are available: Stop a specific timer in the room - **Timer: Toggle playback** Toggle (start/stop) a specific timer in the room +- **Timer: Create new timer** + Create a new timer in the room **Transport actions:** @@ -105,6 +112,7 @@ The following Actions are available: ## Variables +- `$(stagetimer:currentTimerAppearance)` - Timer appearance ([Docs](https://stagetimer.io/docs/using-timers/#timer-appearances)) - `$(stagetimer:currentTimerDuration)` - Timer duration - `$(stagetimer:currentTimerDurationAsMs)` - Timer duration (ms) - `$(stagetimer:currentTimerId)` - Timer ID @@ -112,9 +120,13 @@ The following Actions are available: - `$(stagetimer:currentTimerNotes)` - Timer notes - `$(stagetimer:currentTimerRemaining)` - Timer remaining time - `$(stagetimer:currentTimerRemainingAsMs)` - Timer remaining time (ms) +- `$(stagetimer:currentTimerRemainingHours)` - Timer remaining time (hours) +- `$(stagetimer:currentTimerRemainingMinutes)` - Timer remaining time (minutes) +- `$(stagetimer:currentTimerRemainingSeconds)` - Timer remaining time (seconds) - `$(stagetimer:currentTimerSpeaker)` - Timer speaker - `$(stagetimer:roomId)` - Room ID - `$(stagetimer:roomName)` - Room name +- `$(stagetimer:roomTimezone)` - Room timezone ([Docs](https://stagetimer.io/docs/using-timers/#timezones)) --- From aca3fadea8a9ab167ff5292d64c77a6eec2cbe76 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Fri, 17 Nov 2023 19:53:51 +0100 Subject: [PATCH 17/18] refactor: fix a few strings to match docs --- src/actions.js | 4 ++-- src/presets.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/actions.js b/src/actions.js index 730b5e3..6ac8d4d 100644 --- a/src/actions.js +++ b/src/actions.js @@ -408,7 +408,7 @@ export function loadActions (instance) { }, [actionIdType.create_timer]: { name: 'Timer: Create new timer', - description: 'Creates a new timer in the room', + description: 'Create a new timer in the room', options: actionOptions.timerCreate, callback: actionCallback, }, @@ -434,7 +434,7 @@ export function loadActions (instance) { }, [actionIdType.create_message]: { name: 'Message: Create new message', - description: 'Creates a new message in the room', + description: 'Create a new message in the room', options: actionOptions.messageCreate, callback: actionCallback, }, diff --git a/src/presets.js b/src/presets.js index 384517f..ab074c0 100644 --- a/src/presets.js +++ b/src/presets.js @@ -200,7 +200,7 @@ function generatePresets () { ], }, { - name: 'Timer remaining, hours', + name: 'Time remaining (hours)', actionId: '', style: { size: 'auto', @@ -216,7 +216,7 @@ function generatePresets () { ], }, { - name: 'Timer remaining, minutes', + name: 'Time remaining (minutes)', actionId: '', style: { size: 'auto', @@ -232,7 +232,7 @@ function generatePresets () { ], }, { - name: 'Timer remaining, seconds', + name: 'Time remaining (seconds)', actionId: '', style: { size: 'auto', @@ -249,7 +249,7 @@ function generatePresets () { }, { - name: 'Timer status', + name: 'Wrap-up indicator', actionId: '', style: { size: '18', From e68e72189fa57884e7b23e3578b0d6ad9814e0d8 Mon Sep 17 00:00:00 2001 From: Vanja Cosic <1070957+vanjacosic@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:27:15 +0100 Subject: [PATCH 18/18] chore: Release v2.1.0 --- companion/manifest.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/manifest.json b/companion/manifest.json index 6aebc38..f2c663a 100644 --- a/companion/manifest.json +++ b/companion/manifest.json @@ -3,7 +3,7 @@ "name": "stagetimer", "shortname": "stagetimer", "description": "Stagetimer.io module for Companion v3", - "version": "2.0.0", + "version": "2.1.0", "license": "MIT", "repository": "git+https://github.com/bitfocus/companion-module-stagetimerio-api.git", "bugs": "https://github.com/bitfocus/companion-module-stagetimerio-api/issues", diff --git a/package.json b/package.json index 37046f5..86c7ba3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stagetimerio-api", - "version": "2.0.0", + "version": "2.1.0", "main": "src/index.js", "type": "module", "scripts": {