From 5d3a5eda514ef8b561580dd3899558eb72fd2e82 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2024 16:01:03 +0100 Subject: [PATCH 01/10] Add additional action for a workspace lifecycle event. Added an extra action to make it clear when a workspace was applied. Updated impacted modules. --- how-to/workspace-platform-starter/CHANGELOG.md | 3 +++ .../client/src/framework/platform/platform-override.ts | 2 +- .../client/src/framework/shapes/lifecycle-shapes.ts | 2 +- .../src/modules/composite/default-workspace/lifecycle.ts | 4 +++- .../client/src/modules/integrations/workspaces/integration.ts | 2 +- .../client/types/module/shapes/lifecycle-shapes.d.ts | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index 5018883127..5b22a15952 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,9 @@ ## v18.0.0 +- Improvement: Added `apply` as an action on the WorkspaceChangedLifecyclePayload. Previously we had `create`, `update`, `delete`. `update` was being fired when a workspace was updated and when a workspace was applied. `apply` now makes it clear when a particular workspace platform override has been triggered. +- Improvement: modules/integrations/workspaces this module now refreshes the entries when a workspace is applied. So if a workspace entry in Home said it was selected it would be updated and the newly selected workspace would be updated to reflect it is the currently selected workspace. +- Updated: modules/composite/default-workspace/lifecycle logic to listen out for the new `apply` action. - Added support for rspack for faster builds. `npm run build-client-rspack` will npx install rspack and use the webpack config file to build the JavaScript from the TypeScript files. It is faster but no type checking is performed so we still recommend doing validated builds using `npm run build` or `npm run build-client`. - Improved performance of switching schemes - Improved performance of computing dock configuration, especially on theme changes. diff --git a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts index 81acdb1684..da71225302 100644 --- a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts +++ b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts @@ -412,7 +412,7 @@ export function overrideCallback( } await fireLifecycleEvent(platform, "workspace-changed", { - action: "update", + action: "apply", id: payload.workspaceId, workspace: payload }); diff --git a/how-to/workspace-platform-starter/client/src/framework/shapes/lifecycle-shapes.ts b/how-to/workspace-platform-starter/client/src/framework/shapes/lifecycle-shapes.ts index 54ba206e9a..55b236580d 100644 --- a/how-to/workspace-platform-starter/client/src/framework/shapes/lifecycle-shapes.ts +++ b/how-to/workspace-platform-starter/client/src/framework/shapes/lifecycle-shapes.ts @@ -57,7 +57,7 @@ export interface WorkspaceChangedLifecyclePayload { /** * The action that happened to the workspace. */ - action: "create" | "update" | "delete"; + action: "create" | "apply" | "update" | "delete"; /** * The id of the workspace. diff --git a/how-to/workspace-platform-starter/client/src/modules/composite/default-workspace/lifecycle.ts b/how-to/workspace-platform-starter/client/src/modules/composite/default-workspace/lifecycle.ts index cd13164907..c7ba13c028 100644 --- a/how-to/workspace-platform-starter/client/src/modules/composite/default-workspace/lifecycle.ts +++ b/how-to/workspace-platform-starter/client/src/modules/composite/default-workspace/lifecycle.ts @@ -92,7 +92,9 @@ export class ApplyDefaultWorkspaceProvider implements Lifecycle platform: WorkspacePlatformModule, payload?: WorkspaceChangedLifecyclePayload ): Promise => { - if (payload?.action === "create") { + if (payload?.action === "create" || payload?.action === "apply") { if (!isEmpty(this._lastQuery) && !this._lastQuery.startsWith("/w ")) { await this.rebuildResults(platform); } diff --git a/how-to/workspace-platform-starter/client/types/module/shapes/lifecycle-shapes.d.ts b/how-to/workspace-platform-starter/client/types/module/shapes/lifecycle-shapes.d.ts index 43ffd09d44..f589e1f304 100644 --- a/how-to/workspace-platform-starter/client/types/module/shapes/lifecycle-shapes.d.ts +++ b/how-to/workspace-platform-starter/client/types/module/shapes/lifecycle-shapes.d.ts @@ -51,7 +51,7 @@ export interface WorkspaceChangedLifecyclePayload { /** * The action that happened to the workspace. */ - action: "create" | "update" | "delete"; + action: "create" | "apply" | "update" | "delete"; /** * The id of the workspace. */ From 2b0b4f1c78694048c715c5bf42fedc31e61a8a83 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Apr 2024 17:05:15 +0100 Subject: [PATCH 02/10] Improving FDC3 docs to make it easier to learn about fdc3 (#704) Also added urls if people want to add the tooling to their own platform. --- .../how-to-add-context-support-to-your-app.md | 30 ++++++++ .../how-to-add-intent-support-to-your-app.md | 30 ++++++++ .../docs/what-is-fdc3.md | 71 ++++++++++++++++++- 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md b/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md index daf6cd8955..9675ef4e26 100644 --- a/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md +++ b/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md @@ -190,6 +190,36 @@ This app supports FDC3 System and App Channels, lists all the supported context ![Context Using FDC3](./assets/view-context-fdc3.png) +#### Can I use that tool within my own platform? + +Yes, to make development easier you can define a view that uses our app. We follow the versioning used by workspace so that you can stay in sync: + +##### FDC3 2.0 Tool - View Options + +```javascript +{ + "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/context/2-0/fdc3-broadcast-view.html", + "fdc3InteropApi": "2.0", + "customData": { + "contextData": null, + "customChannel": "" + } +} +``` + +##### FDC3 1.2 Tool - View Options + +```javascript +{ + "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/context/fdc3-broadcast-view.html", + "fdc3InteropApi": "1.2", + "customData": { + "contextData": null, + "customChannel": "" + } +} +``` + ### FDC3 Workbench This is the FinOS test harness to show our compatibility: diff --git a/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md b/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md index 980e1b400a..e317aca71f 100644 --- a/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md +++ b/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md @@ -129,6 +129,36 @@ This app supports FDC3 raiseIntent and raiseIntentByContext, it lists all the su ![Intents Using FDC3](./assets/view-intents-fdc3.png) +#### Can I use that tool within my own platform? + +Yes, to make development easier you can define a view that uses our app. We follow the versioning used by workspace so that you can stay in sync: + +##### FDC3 2.0 Tool - View Options + +```javascript +{ + "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/intent/2-0/fdc3-intent-view.html", + "fdc3InteropApi": "2.0", + "customData": { + "contextData": null, + "intentData": null + } +} +``` + +##### FDC3 1.2 Tool - View Options + +```javascript +{ + "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/intent/fdc3-intent-view.html", + "fdc3InteropApi": "1.2", + "customData": { + "contextData": null, + "intentData": null + } +} +``` + ### FDC3 Workbench This is the FinOS test harness to show our compatibility: diff --git a/how-to/workspace-platform-starter/docs/what-is-fdc3.md b/how-to/workspace-platform-starter/docs/what-is-fdc3.md index 4a90894f20..d0322f4a69 100644 --- a/how-to/workspace-platform-starter/docs/what-is-fdc3.md +++ b/how-to/workspace-platform-starter/docs/what-is-fdc3.md @@ -26,6 +26,75 @@ As a content creator: - Whether you content will listen for intent requests - What intents you wish to declare that you support in your app definition -We provide guides on [how to configure contextual groups](./how-to-configure-fdc3-context-groups.md) and [how to configure intents](./how-to-configure-fdc3-intents.md) for your workspace platform and [how to add context support](./how-to-add-context-support-to-your-app.md), [how to add intent support](./how-to-add-intent-support-to-your-app.md) and [how to add fdc3 open support](./how-to-add-open-support-to-your-app.md) to your content/app. We recommend going through the concepts and working your way down the guides if you are new to OpenFin and OpenFin Workspace. We also provide a configured workspace (see [third.manifest.fin.json](../public/third.manifest.fin.json)) that is configured to use an FDC3 App Directory and only brings in FDC3 related tools. +## Useful links + +- - FDC3 related content on the OpenFin website +- - The official fdc3 content. +- - Linux Foundation's free Introduction to FDC3 course. + +## Enabling FDC3 in your Openfin Application + +### Manifest + +In your manifest you can define default Window Options and default View Options. You can specify that you wish FDC3 (and what version) enabled for all views and windows in your manifest: + +```js +"platform": { + "defaultWindowOptions": { + "fdc3InteropApi" : '2.0' + }, + "defaultViewOptions": { + "fdc3InteropApi" : '2.0' + } +} +``` + +In your manifest within the platform definition you can also enable/disable the FDC3/Interop console logging OpenFin does (it is true by default): + +```js +"platform": { + "interopBrokerConfiguration": { + "logging": { + "beforeAction": { + "enabled": true + }, + "afterAction": { + "enabled": true + } + } + } +} +``` + +### Window / View Options + +If you do not globally enable the fdc3 API you can opt into FDC3 at the Window/View level via Window/View options. + +#### Enabling the FDC3 API + +```js +{ + "url": "http://yoururl", + "fdc3InteropApi" : '2.0' +} +``` + +#### Defaulting to a user channel + +You can have a view/window automatically join a user channel if it is specified in the View/Window Options + +```js +{ + "url": "http://yoururl", + "fdc3InteropApi": "2.0", + "interop": { + "currentContextGroup": "green" + }, +} +``` + +## Guides + +We provide guides on [how to configure intents](./how-to-configure-fdc3-intents.md) for your workspace platform and [how to add context support](./how-to-add-context-support-to-your-app.md), [how to add intent support](./how-to-add-intent-support-to-your-app.md) and [how to add fdc3 open support](./how-to-add-open-support-to-your-app.md) to your content/app. We recommend going through the concepts and working your way down the guides if you are new to OpenFin and OpenFin Workspace. We also provide a configured workspace (see [third.manifest.fin.json](../public/third.manifest.fin.json)) that is configured to use an FDC3 App Directory and only brings in FDC3 related tools. [<- Back to Table Of Contents](../README.md) From 194d60cfe5bf685178d7dd3175b0d401bbf1bd57 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 10:05:13 +0100 Subject: [PATCH 03/10] Update versioning in docs --- .../docs/how-to-add-context-support-to-your-app.md | 4 ++-- .../docs/how-to-add-intent-support-to-your-app.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md b/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md index 9675ef4e26..ef502afd1d 100644 --- a/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md +++ b/how-to/workspace-platform-starter/docs/how-to-add-context-support-to-your-app.md @@ -198,7 +198,7 @@ Yes, to make development easier you can define a view that uses our app. We foll ```javascript { - "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/context/2-0/fdc3-broadcast-view.html", + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/context/2-0/fdc3-broadcast-view.html", "fdc3InteropApi": "2.0", "customData": { "contextData": null, @@ -211,7 +211,7 @@ Yes, to make development easier you can define a view that uses our app. We foll ```javascript { - "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/context/fdc3-broadcast-view.html", + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/context/fdc3-broadcast-view.html", "fdc3InteropApi": "1.2", "customData": { "contextData": null, diff --git a/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md b/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md index e317aca71f..bfe3442402 100644 --- a/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md +++ b/how-to/workspace-platform-starter/docs/how-to-add-intent-support-to-your-app.md @@ -137,7 +137,7 @@ Yes, to make development easier you can define a view that uses our app. We foll ```javascript { - "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/intent/2-0/fdc3-intent-view.html", + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/intent/2-0/fdc3-intent-view.html", "fdc3InteropApi": "2.0", "customData": { "contextData": null, @@ -150,7 +150,7 @@ Yes, to make development easier you can define a view that uses our app. We foll ```javascript { - "url": "https://samples.openfin.co/dev-extensions/extensions/v17.2.0/interop/fdc3/intent/fdc3-intent-view.html", + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/intent/fdc3-intent-view.html", "fdc3InteropApi": "1.2", "customData": { "contextData": null, From 11f4a28e783eafb765ee77ad3174c4a839261f67 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 12:47:48 +0100 Subject: [PATCH 04/10] Window state improvements and dependency pinning. Also added optimization for module --- .../client/src/framework/modules.ts | 1 + .../client/src/framework/platform/browser.ts | 26 +- .../framework/platform/platform-override.ts | 23 +- .../client/webpack.config.js | 2 +- package-lock.json | 4109 ++++++++--------- package.json | 3 + 6 files changed, 1970 insertions(+), 2194 deletions(-) diff --git a/how-to/workspace-platform-starter/client/src/framework/modules.ts b/how-to/workspace-platform-starter/client/src/framework/modules.ts index 1ab96fec69..ba698be277 100644 --- a/how-to/workspace-platform-starter/client/src/framework/modules.ts +++ b/how-to/workspace-platform-starter/client/src/framework/modules.ts @@ -322,6 +322,7 @@ export function getDefaultHelpers(): ModuleHelpers { pageId: string, options?: { bounds?: OpenFin.Bounds; + state?: "normal" | "minimized" | "maximized"; targetWindowIdentity?: OpenFin.Identity; createCopyIfExists?: boolean; }, diff --git a/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts b/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts index b203c88472..dce6e76b7c 100644 --- a/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts +++ b/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts @@ -299,16 +299,16 @@ export async function getPageForView(view: OpenFin.View): Promise { - let bounds: OpenFin.Bounds | undefined; +): Promise<{ bounds?: OpenFin.Bounds; state?: "maximized" | "minimized" | "normal"} | undefined> { + let boundsAndState: { bounds?: OpenFin.Bounds; state?: "maximized" | "minimized" | "normal"} | undefined; const platform = getCurrentSync(); if (fromStorage) { const page = await platform.Storage.getPage(pageId); if (!isEmpty(page?.customData?.windowBounds)) { - return page?.customData?.windowBounds; + return { bounds: page?.customData?.windowBounds, state: page?.customData?.windowState }; } } @@ -327,7 +327,7 @@ export async function getPageBounds( const savedPage = await platform.Storage.getPage(pageId); if (!isEmpty(savedPage)) { // the requested page is not currently open but is a saved page so try and fetch it from storage as a fallback - return savedPage?.customData?.windowBounds; + return { bounds: savedPage?.customData?.windowBounds, state: savedPage?.customData?.windowState }; } // it is not an active page and it isn't saved so it is likely a new instance of an existing page (save as) // use the current windowId @@ -336,10 +336,11 @@ export async function getPageBounds( if (!isEmpty(windowId)) { const hostWindow = platform.Browser.wrapSync(windowId); - bounds = await hostWindow.openfinWindow.getBounds(); + boundsAndState = { bounds: await hostWindow.openfinWindow.getBounds(), + state: await hostWindow.openfinWindow.getState() }; } - return bounds; + return boundsAndState; } /** @@ -347,6 +348,7 @@ export async function getPageBounds( * @param page The page to launch. * @param options The options for the launch. * @param options.bounds The optional bounds for the page. + * @param options.state The optional window state of the page. * @param options.targetWindowIdentity The optional target window for the page. * @param options.createCopyIfExists Create a copy of the page if it exists. * @param logger Log output from the operation. @@ -356,6 +358,7 @@ export async function launchPage( page: Page, options?: { bounds?: OpenFin.Bounds; + state?: "maximized" | "minimized" | "normal"; targetWindowIdentity?: OpenFin.Identity; createCopyIfExists?: boolean; }, @@ -441,7 +444,10 @@ export async function launchPage( if (isEmpty(customBounds) && !isEmpty(page.customData?.windowBounds)) { customBounds = page.customData.windowBounds; } - + let customState = options?.state; + if (isEmpty(customState) && !isEmpty(page.customData?.windowState)) { + customState = page.customData.windowState; + } const newWindowRequest: BrowserCreateWindowRequest = { workspacePlatform: { pages: [page] @@ -469,6 +475,10 @@ export async function launchPage( } } + if(!isEmpty(customState)) { + newWindowRequest.state = customState; + } + const newWindow = await platform.Browser.createWindow(newWindowRequest); logger?.info("Page does not exist, creating new window and adding page", { diff --git a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts index da71225302..2d5a1b0430 100644 --- a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts +++ b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts @@ -69,7 +69,7 @@ import { applyClientSnapshot, decorateSnapshot } from "../snapshot-source"; import { setCurrentColorSchemeMode } from "../themes"; import { deepMerge, isEmpty, isStringValue, randomUUID } from "../utils"; import { loadConfig, saveConfig } from "../workspace/dock"; -import { getPageBounds } from "./browser"; +import { getPageBoundsAndState } from "./browser"; import { closedown as closedownPlatform } from "./platform"; import { mapPlatformPageFromStorage, @@ -490,13 +490,19 @@ export function overrideCallback( */ public async createSavedPage(req: CreateSavedPageRequest): Promise { const platform = getCurrentSync(); - - const windowBounds = await getPageBounds(req.page.pageId); - if (!isEmpty(windowBounds)) { + const windowBoundsAndState = await getPageBoundsAndState(req.page.pageId); + if (!isEmpty(windowBoundsAndState)) { if (isEmpty(req.page.customData)) { req.page.customData = {}; } - req.page.customData.windowBounds = windowBounds; + // only set if it hasn't been provided by the caller + if(isEmpty(req.page?.customData?.windowBounds)) { + req.page.customData.windowBounds = windowBoundsAndState.bounds; + } + + if(isEmpty(req.page?.customData?.windowState)) { + req.page.customData.windowState = windowBoundsAndState.state; + } } // you can add your own custom implementation here if you are storing your pages @@ -540,12 +546,13 @@ export function overrideCallback( * @param req the update saved page request. */ public async updateSavedPage(req: UpdateSavedPageRequest): Promise { - const windowBounds = await getPageBounds(req.page.pageId); - if (!isEmpty(windowBounds)) { + const windowBoundsAndState = await getPageBoundsAndState(req.page.pageId); + if (!isEmpty(windowBoundsAndState)) { if (isEmpty(req.page.customData)) { req.page.customData = {}; } - req.page.customData.windowBounds = windowBounds; + req.page.customData.windowBounds = windowBoundsAndState.bounds; + req.page.customData.windowState = windowBoundsAndState.state; } // you can add your own custom implementation here if you are storing your pages // in non-default location (e.g. on the server instead of locally) diff --git a/how-to/workspace-platform-starter/client/webpack.config.js b/how-to/workspace-platform-starter/client/webpack.config.js index 491570875f..141e24a874 100644 --- a/how-to/workspace-platform-starter/client/webpack.config.js +++ b/how-to/workspace-platform-starter/client/webpack.config.js @@ -774,7 +774,7 @@ const configs = [ }, { entry: './client/src/modules/interop-override/wps-interop-override/index.ts', - devtool: 'inline-source-map', + devtool: 'source-map', module: { rules: [loaderRule] }, diff --git a/package-lock.json b/package-lock.json index 1bb9ba3816..d8fbd5a6bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,38 +34,6 @@ "mochawesome": "7.1.3" } }, - "how-to/automation-testing/register-with-home-js/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "how-to/automation-testing/register-with-home-js/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "how-to/automation-testing/register-with-home-js/node_modules/jasmine": { "version": "2.99.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz", @@ -90,19 +58,6 @@ "jasmine": "^2.4.1" } }, - "how-to/automation-testing/register-with-home-js/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "how-to/automation-testing/register-with-home-ts": { "name": "automation-testing-register-with-home", "version": "18.0.0", @@ -141,27 +96,23 @@ "selenium-webdriver": "4.18.1" } }, - "how-to/automation-testing/selenium/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "how-to/automation-testing/selenium/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "how-to/automation-testing/selenium/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "how-to/automation-testing/selenium/node_modules/mocha": { @@ -213,42 +164,6 @@ "node": ">= 14.20.0" } }, - "how-to/automation-testing/selenium/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "how-to/automation-testing/selenium/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "how-to/automation-testing/selenium/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -267,15 +182,6 @@ "node": ">=10" } }, - "how-to/automation-testing/selenium/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "how-to/automation-testing/wdio": { "name": "automation-testing-wdio", "version": "18.0.0", @@ -2168,12 +2074,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -2531,48 +2431,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -3779,9 +3637,9 @@ } }, "node_modules/@openfin/bloomberg/node_modules/@finos/fdc3": { - "version": "2.1.0-beta.6", - "resolved": "https://registry.npmjs.org/@finos/fdc3/-/fdc3-2.1.0-beta.6.tgz", - "integrity": "sha512-iKrAY8I6k2sWYBZ+fW0Iz5IvUHV/A3lsb/7dtkjnJhN2dzFX1HfzJ4mgMAqmXk9HNSgP8lS3hOt2DC/kiApNiA==" + "version": "2.1.0-beta.7", + "resolved": "https://registry.npmjs.org/@finos/fdc3/-/fdc3-2.1.0-beta.7.tgz", + "integrity": "sha512-YtNKYPk2daq4ByS7WccRiYxTi80/GXTPObYmbNiS9OXA4+Er/JwCB77CkVCL+TQ8z/LWzPulR+w4PParLTXdKA==" }, "node_modules/@openfin/core": { "version": "36.80.8", @@ -3797,6 +3655,31 @@ "ws": "^7.3.0" } }, + "node_modules/@openfin/core/node_modules/@types/node": { + "version": "16.18.96", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.96.tgz", + "integrity": "sha512-84iSqGXoO+Ha16j8pRZ/L90vDMKX04QTYMTfYeE1WrjWaZXuchBehGUZEpNgx7JnmlrIHdnABmpjrQjhCnNldQ==" + }, + "node_modules/@openfin/core/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@openfin/excel": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@openfin/excel/-/excel-1.5.0.tgz", @@ -3843,6 +3726,33 @@ "ws": "^7.3.0" } }, + "node_modules/@openfin/node-adapter/node_modules/@types/node": { + "version": "16.18.96", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.96.tgz", + "integrity": "sha512-84iSqGXoO+Ha16j8pRZ/L90vDMKX04QTYMTfYeE1WrjWaZXuchBehGUZEpNgx7JnmlrIHdnABmpjrQjhCnNldQ==", + "dev": true + }, + "node_modules/@openfin/node-adapter/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@openfin/openid-connect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@openfin/openid-connect/-/openid-connect-1.0.0.tgz", @@ -4015,48 +3925,114 @@ "node": ">=16.3.0" } }, - "node_modules/@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "node_modules/@puppeteer/browsers/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10" + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "node_modules/@puppeteer/browsers/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">= 14" } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", - "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "node_modules/@puppeteer/browsers/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2" - }, + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@puppeteer/browsers/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", @@ -4568,83 +4544,83 @@ } }, "node_modules/@sentry-internal/feedback": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.109.0.tgz", - "integrity": "sha512-EL7N++poxvJP9rYvh6vSu24tsKkOveNCcCj4IM7+irWPjsuD2GLYYlhp/A/Mtt9l7iqO4plvtiQU5HGk7smcTQ==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.110.0.tgz", + "integrity": "sha512-hrfWa3WkSOiBO5Srcr1j4kuGOlbsQic+REpLOofllVIs56DOo9+Aj9svxT+dcvZERv/nlFSV/E0BfGy9g08IEg==", "dependencies": { - "@sentry/core": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry/core": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.109.0.tgz", - "integrity": "sha512-Lh/K60kmloR6lkPUcQP0iamw7B/MdEUEx/ImAx4tUSMrLj+IoUEcq/ECgnnVyQkJq59+8nPEKrVLt7x6PUPEjw==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.110.0.tgz", + "integrity": "sha512-SNa+AfyfX+vc6Xw0pIfDsa5Qnc9cpexU6M2D19gadtVhmep7qoFBuhBVZrSv6BtdCxvrb5EyYsHYGfjQdIDcvg==", "dependencies": { - "@sentry/core": "7.109.0", - "@sentry/replay": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry/core": "7.110.0", + "@sentry/replay": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry-internal/tracing": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.109.0.tgz", - "integrity": "sha512-PzK/joC5tCuh2R/PRh+7dp+uuZl7pTsBIjPhVZHMTtb9+ls65WkdZJ1/uKXPouyz8NOo9Xok7aEvEo9seongyw==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.110.0.tgz", + "integrity": "sha512-IIHHa9e/mE7uOMJfNELI8adyoELxOy6u6TNCn5t6fphmq84w8FTc9adXkG/FY2AQpglkIvlILojfMROFB2aaAQ==", "dependencies": { - "@sentry/core": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry/core": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/browser": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.109.0.tgz", - "integrity": "sha512-yx+OFG+Ab9qUDDgV9ZDv8M9O9Mqr0fjKta/LMlWALYLjzkMvxsPlRPFj7oMBlHqOTVLDeg7lFYmsA8wyWQ8Z8g==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.110.0.tgz", + "integrity": "sha512-gIxedVm6ZgkjQfgCDgLWJgAsolq6OxV8hQ2j1+RaDL2RngvelFo/vlX5f2sD6EbjVp77Cri8u5GkMJF+v4p84g==", "dependencies": { - "@sentry-internal/feedback": "7.109.0", - "@sentry-internal/replay-canvas": "7.109.0", - "@sentry-internal/tracing": "7.109.0", - "@sentry/core": "7.109.0", - "@sentry/replay": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry-internal/feedback": "7.110.0", + "@sentry-internal/replay-canvas": "7.110.0", + "@sentry-internal/tracing": "7.110.0", + "@sentry/core": "7.110.0", + "@sentry/replay": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.109.0.tgz", - "integrity": "sha512-xwD4U0IlvvlE/x/g/W1I8b4Cfb16SsCMmiEuBf6XxvAa3OfWBxKoqLifb3GyrbxMC4LbIIZCN/SvLlnGJPgszA==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.110.0.tgz", + "integrity": "sha512-g4suCQO94mZsKVaAbyD1zLFC5YSuBQCIPHXx9fdgtfoPib7BWjWWePkllkrvsKAv4u8Oq05RfnKOhOMRHpOKqg==", "dependencies": { - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/react": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.109.0.tgz", - "integrity": "sha512-KqXoDh6LVhNO+FLdM5LiTGpuorFvjoBPQ4nPGIVbjeMY/KZIau3kFxR142EvCApxmD69yvS5EhMnEqlNdaQPGw==", - "dependencies": { - "@sentry/browser": "7.109.0", - "@sentry/core": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.110.0.tgz", + "integrity": "sha512-ryfA2QR41PV+kP3g0lGvpDZ+OkuxSdj2nTjCqPeZKHsK45GYvDMlWkukdHbwrx8ulkbAcWEjPmuZZzHspyieNw==", + "dependencies": { + "@sentry/browser": "7.110.0", + "@sentry/core": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -4655,33 +4631,33 @@ } }, "node_modules/@sentry/replay": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.109.0.tgz", - "integrity": "sha512-hCDjbTNO7ErW/XsaBXlyHFsUhneyBUdTec1Swf98TFEfVqNsTs6q338aUcaR8dGRLbLrJ9YU9D1qKq++v5h2CA==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.110.0.tgz", + "integrity": "sha512-EEpGPf3iBJjWejvoxKLVMnLtLNwPTUxHJV1oxUkbcSi3B/tG5hW7LArYDjAcvkfa4VmA8JLCwj2vYU5MQ8tj6g==", "dependencies": { - "@sentry-internal/tracing": "7.109.0", - "@sentry/core": "7.109.0", - "@sentry/types": "7.109.0", - "@sentry/utils": "7.109.0" + "@sentry-internal/tracing": "7.110.0", + "@sentry/core": "7.110.0", + "@sentry/types": "7.110.0", + "@sentry/utils": "7.110.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/types": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.109.0.tgz", - "integrity": "sha512-egCBnDv3YpVFoNzRLdP0soVrxVLCQ+rovREKJ1sw3rA2/MFH9WJ+DZZexsX89yeAFzy1IFsCp7/dEqudusml6g==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.110.0.tgz", + "integrity": "sha512-DqYBLyE8thC5P5MuPn+sj8tL60nCd/f5cerFFPcudn5nJ4Zs1eI6lKlwwyHYTEu5c4KFjCB0qql6kXfwAHmTyA==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.109.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.109.0.tgz", - "integrity": "sha512-3RjxMOLMBwZ5VSiH84+o/3NY2An4Zldjz0EbfEQNRY9yffRiCPJSQiCJID8EoylCFOh/PAhPimBhqbtWJxX6iw==", + "version": "7.110.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.110.0.tgz", + "integrity": "sha512-VBsdLLN+5tf73fhf/Cm7JIsUJ6y9DkJj8h4I6Mxx0rszrvOyH6S5px40K+V4jdLBzMEvVinC7q2Cbf1YM18BSw==", "dependencies": { - "@sentry/types": "7.109.0" + "@sentry/types": "7.110.0" }, "engines": { "node": ">=8" @@ -4896,9 +4872,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.7.tgz", - "integrity": "sha512-SjDvI/x3zsZnOkYZ3lCt9lOZWZLB2jIlNKz+LBgCtDurK0JZcwucxYHn1w2BJkD34dgX9Tjnak0txtq4WTggEA==", + "version": "8.56.9", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", + "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -5053,9 +5029,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.96", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.96.tgz", - "integrity": "sha512-84iSqGXoO+Ha16j8pRZ/L90vDMKX04QTYMTfYeE1WrjWaZXuchBehGUZEpNgx7JnmlrIHdnABmpjrQjhCnNldQ==" + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-emoji": { "version": "1.8.2", @@ -5087,9 +5066,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.75", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.75.tgz", - "integrity": "sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==", + "version": "18.2.77", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.77.tgz", + "integrity": "sha512-CUT9KUUF+HytDM7WiXKLF9qUSg4tGImwy4FXTlfEDPEkkNUzJ7rVFolYweJ9fS1ljoIaP7M7Rdjc5eUm/Yu5AA==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5413,9 +5392,9 @@ "dev": true }, "node_modules/@vitest/snapshot": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz", - "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.0.tgz", + "integrity": "sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -5464,13 +5443,46 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/cli/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "node_modules/@wdio/cli/node_modules/@wdio/config": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.34.0.tgz", + "integrity": "sha512-dtVGW/QEqM/WLUEZvca09y12L+hMZnzuwGuSzdG8B3wT6OaT+lSktU842HqHPC7OnZ27kRORhDJM6JLDy1T7dw==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.33.1", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.0.0", + "glob": "^10.2.2", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/cli/node_modules/@wdio/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", + "dev": true, + "dependencies": { + "@puppeteer/browsers": "^1.6.0", + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.1.0", + "edgedriver": "^5.3.5", + "geckodriver": "^4.3.1", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.1.0", + "safaridriver": "^0.1.0", + "split2": "^4.2.0", + "wait-port": "^1.0.4" + }, + "engines": { + "node": "^16.13 || >=18" } }, "node_modules/@wdio/cli/node_modules/chalk": { @@ -5485,16 +5497,37 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@wdio/cli/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@wdio/cli/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@wdio/cli/node_modules/devtools-protocol": { "version": "0.0.1263784", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1263784.tgz", "integrity": "sha512-k0SCZMwj587w4F8QYbP5iIbSonL6sd3q8aVJch036r9Tv2t9b5/Oq7AiJ/FJvRuORm/pJNXZtrdNNWlpRnl56A==", "dev": true }, - "node_modules/@wdio/cli/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/@wdio/cli/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "engines": { "node": ">=12" @@ -5503,116 +5536,563 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@wdio/cli/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "node_modules/@wdio/cli/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16.17" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@wdio/cli/node_modules/webdriver": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.34.0.tgz", - "integrity": "sha512-r8oe6tIm2qSdLNhzwVpVMWJvuoZTbeTZI21+EidqZtp6krlnJzd+hIRD5ojTm+yYi86JlRQnMMQ40LUBsAGVsQ==", + "node_modules/@wdio/cli/node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dev": true, "dependencies": { - "@types/node": "^20.1.0", - "@types/ws": "^8.5.3", - "@wdio/config": "8.34.0", - "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.32.0", - "@wdio/types": "8.32.4", - "@wdio/utils": "8.33.1", - "deepmerge-ts": "^5.1.0", - "got": "^12.6.1", - "ky": "^0.33.0", - "ws": "^8.8.0" + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" }, "engines": { - "node": "^16.13 || >=18" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@wdio/cli/node_modules/webdriverio": { - "version": "8.34.1", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.34.1.tgz", - "integrity": "sha512-9C+sy8mkvIGdKFFHL5oq6s2Uhq1lsAXybG3MsF0QA2822Jm+oYHN4KohrOGF0yBJc/x5JRaW3/hXvldnj7a55A==", + "node_modules/@wdio/cli/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "dependencies": { - "@types/node": "^20.1.0", - "@wdio/config": "8.34.0", - "@wdio/logger": "8.28.0", - "@wdio/protocols": "8.32.0", - "@wdio/repl": "8.24.12", - "@wdio/types": "8.32.4", - "@wdio/utils": "8.33.1", - "archiver": "^7.0.0", - "aria-query": "^5.0.0", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools-protocol": "^0.0.1263784", - "grapheme-splitter": "^1.0.2", - "import-meta-resolve": "^4.0.0", - "is-plain-obj": "^4.1.0", - "lodash.clonedeep": "^4.5.0", - "lodash.zip": "^4.2.0", - "minimatch": "^9.0.0", - "puppeteer-core": "^20.9.0", - "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.5", - "serialize-error": "^11.0.1", - "webdriver": "8.34.0" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, "engines": { - "node": "^16.13 || >=18" - }, - "peerDependencies": { - "devtools": "^8.14.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "devtools": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@wdio/cli/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "node_modules/@wdio/cli/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node": ">=16" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wdio/cli/node_modules/hosted-git-info": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/@wdio/cli/node_modules/inquirer": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", + "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", + "dev": true, + "dependencies": { + "@ljharb/through": "^2.3.11", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@wdio/cli/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@wdio/cli/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wdio/cli/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/normalize-package-data": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", + "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/parse-json": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@wdio/cli/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/read-pkg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", + "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^6.0.0", + "parse-json": "^7.0.0", + "type-fest": "^4.2.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/read-pkg-up": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.0.0.tgz", + "integrity": "sha512-jgmKiS//w2Zs+YbX039CorlkOp8FIVbSAN8r8GJHDsGlmNPXo+VeHkqAwCiQVTTx5/LwLZTcEw59z3DvcLbr0g==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0", + "read-pkg": "^8.0.0", + "type-fest": "^3.12.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@wdio/config": { + "node_modules/@wdio/cli/node_modules/read-pkg/node_modules/type-fest": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.15.0.tgz", + "integrity": "sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/@wdio/cli/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@wdio/cli/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/cli/node_modules/webdriver": { "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.34.0.tgz", - "integrity": "sha512-dtVGW/QEqM/WLUEZvca09y12L+hMZnzuwGuSzdG8B3wT6OaT+lSktU842HqHPC7OnZ27kRORhDJM6JLDy1T7dw==", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.34.0.tgz", + "integrity": "sha512-r8oe6tIm2qSdLNhzwVpVMWJvuoZTbeTZI21+EidqZtp6krlnJzd+hIRD5ojTm+yYi86JlRQnMMQ40LUBsAGVsQ==", + "dev": true, + "dependencies": { + "@types/node": "^20.1.0", + "@types/ws": "^8.5.3", + "@wdio/config": "8.34.0", + "@wdio/logger": "8.28.0", + "@wdio/protocols": "8.32.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.33.1", + "deepmerge-ts": "^5.1.0", + "got": "^12.6.1", + "ky": "^0.33.0", + "ws": "^8.8.0" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/cli/node_modules/webdriverio": { + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.34.1.tgz", + "integrity": "sha512-9C+sy8mkvIGdKFFHL5oq6s2Uhq1lsAXybG3MsF0QA2822Jm+oYHN4KohrOGF0yBJc/x5JRaW3/hXvldnj7a55A==", "dev": true, "dependencies": { + "@types/node": "^20.1.0", + "@wdio/config": "8.34.0", "@wdio/logger": "8.28.0", + "@wdio/protocols": "8.32.0", + "@wdio/repl": "8.24.12", "@wdio/types": "8.32.4", "@wdio/utils": "8.33.1", + "archiver": "^7.0.0", + "aria-query": "^5.0.0", + "css-shorthand-properties": "^1.1.1", + "css-value": "^0.0.1", + "devtools-protocol": "^0.0.1263784", + "grapheme-splitter": "^1.0.2", + "import-meta-resolve": "^4.0.0", + "is-plain-obj": "^4.1.0", + "lodash.clonedeep": "^4.5.0", + "lodash.zip": "^4.2.0", + "minimatch": "^9.0.0", + "puppeteer-core": "^20.9.0", + "query-selector-shadow-dom": "^1.0.0", + "resq": "^1.9.1", + "rgb2hex": "0.2.5", + "serialize-error": "^11.0.1", + "webdriver": "8.34.0" + }, + "engines": { + "node": "^16.13 || >=18" + }, + "peerDependencies": { + "devtools": "^8.14.0" + }, + "peerDependenciesMeta": { + "devtools": { + "optional": true + } + } + }, + "node_modules/@wdio/cli/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wdio/cli/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@wdio/config": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.35.0.tgz", + "integrity": "sha512-I36sBPMl/+LCyQ3Pwb8gGQM6KxwmUfhOPp16TxN21Qo/Bc0fZfyGIg6KevmRu4DuqpGUm5MMVSfyPhLUkMk3Cg==", + "dev": true, + "dependencies": { + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.35.0", "decamelize": "^6.0.0", "deepmerge-ts": "^5.0.0", "glob": "^10.2.2", @@ -5622,6 +6102,18 @@ "node": "^16.13 || >=18" } }, + "node_modules/@wdio/config/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@wdio/config/node_modules/glob": { "version": "10.3.12", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", @@ -5672,14 +6164,61 @@ "webdriverio": "8.34.1" } }, - "node_modules/@wdio/globals/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "node_modules/@wdio/globals/node_modules/@wdio/config": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.34.0.tgz", + "integrity": "sha512-dtVGW/QEqM/WLUEZvca09y12L+hMZnzuwGuSzdG8B3wT6OaT+lSktU842HqHPC7OnZ27kRORhDJM6JLDy1T7dw==", "dev": true, "optional": true, "dependencies": { - "undici-types": "~5.26.4" + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.33.1", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.0.0", + "glob": "^10.2.2", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/globals/node_modules/@wdio/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", + "dev": true, + "optional": true, + "dependencies": { + "@puppeteer/browsers": "^1.6.0", + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.1.0", + "edgedriver": "^5.3.5", + "geckodriver": "^4.3.1", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.1.0", + "safaridriver": "^0.1.0", + "split2": "^4.2.0", + "wait-port": "^1.0.4" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/globals/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "optional": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@wdio/globals/node_modules/devtools-protocol": { @@ -5689,6 +6228,29 @@ "dev": true, "optional": true }, + "node_modules/@wdio/globals/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dev": true, + "optional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@wdio/globals/node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -5768,41 +6330,19 @@ "minimatch": "^9.0.0", "puppeteer-core": "^20.9.0", "query-selector-shadow-dom": "^1.0.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.5", - "serialize-error": "^11.0.1", - "webdriver": "8.34.0" - }, - "engines": { - "node": "^16.13 || >=18" - }, - "peerDependencies": { - "devtools": "^8.14.0" - }, - "peerDependenciesMeta": { - "devtools": { - "optional": true - } - } - }, - "node_modules/@wdio/globals/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "optional": true, + "resq": "^1.9.1", + "rgb2hex": "0.2.5", + "serialize-error": "^11.0.1", + "webdriver": "8.34.0" + }, "engines": { - "node": ">=10.0.0" + "node": "^16.13 || >=18" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "devtools": "^8.14.0" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "devtools": { "optional": true } } @@ -5826,15 +6366,6 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/local-runner/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@wdio/logger": { "version": "8.28.0", "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.28.0.tgz", @@ -5906,13 +6437,40 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/mocha-framework/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "node_modules/@wdio/mocha-framework/node_modules/@wdio/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@puppeteer/browsers": "^1.6.0", + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.1.0", + "edgedriver": "^5.3.5", + "geckodriver": "^4.3.1", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.1.0", + "safaridriver": "^0.1.0", + "split2": "^4.2.0", + "wait-port": "^1.0.4" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/mocha-framework/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@wdio/protocols": { @@ -5933,15 +6491,6 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@wdio/reporter": { "version": "8.32.4", "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.32.4.tgz", @@ -5958,15 +6507,6 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/reporter/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@wdio/runner": { "version": "8.34.1", "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.34.1.tgz", @@ -5989,13 +6529,58 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/runner/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "node_modules/@wdio/runner/node_modules/@wdio/config": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.34.0.tgz", + "integrity": "sha512-dtVGW/QEqM/WLUEZvca09y12L+hMZnzuwGuSzdG8B3wT6OaT+lSktU842HqHPC7OnZ27kRORhDJM6JLDy1T7dw==", + "dev": true, + "dependencies": { + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.33.1", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.0.0", + "glob": "^10.2.2", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/runner/node_modules/@wdio/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@puppeteer/browsers": "^1.6.0", + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.1.0", + "edgedriver": "^5.3.5", + "geckodriver": "^4.3.1", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.1.0", + "safaridriver": "^0.1.0", + "split2": "^4.2.0", + "wait-port": "^1.0.4" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/runner/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@wdio/runner/node_modules/devtools-protocol": { @@ -6004,6 +6589,28 @@ "integrity": "sha512-k0SCZMwj587w4F8QYbP5iIbSonL6sd3q8aVJch036r9Tv2t9b5/Oq7AiJ/FJvRuORm/pJNXZtrdNNWlpRnl56A==", "dev": true }, + "node_modules/@wdio/runner/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@wdio/runner/node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -6096,27 +6703,6 @@ } } }, - "node_modules/@wdio/runner/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@wdio/shared-store-service": { "version": "8.34.1", "resolved": "https://registry.npmjs.org/@wdio/shared-store-service/-/shared-store-service-8.34.1.tgz", @@ -6134,13 +6720,58 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/shared-store-service/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "node_modules/@wdio/shared-store-service/node_modules/@wdio/config": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.34.0.tgz", + "integrity": "sha512-dtVGW/QEqM/WLUEZvca09y12L+hMZnzuwGuSzdG8B3wT6OaT+lSktU842HqHPC7OnZ27kRORhDJM6JLDy1T7dw==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "@wdio/utils": "8.33.1", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.0.0", + "glob": "^10.2.2", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/shared-store-service/node_modules/@wdio/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", + "dev": true, + "dependencies": { + "@puppeteer/browsers": "^1.6.0", + "@wdio/logger": "8.28.0", + "@wdio/types": "8.32.4", + "decamelize": "^6.0.0", + "deepmerge-ts": "^5.1.0", + "edgedriver": "^5.3.5", + "geckodriver": "^4.3.1", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.1.0", + "safaridriver": "^0.1.0", + "split2": "^4.2.0", + "wait-port": "^1.0.4" + }, + "engines": { + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/shared-store-service/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@wdio/shared-store-service/node_modules/devtools-protocol": { @@ -6149,6 +6780,28 @@ "integrity": "sha512-k0SCZMwj587w4F8QYbP5iIbSonL6sd3q8aVJch036r9Tv2t9b5/Oq7AiJ/FJvRuORm/pJNXZtrdNNWlpRnl56A==", "dev": true }, + "node_modules/@wdio/shared-store-service/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@wdio/shared-store-service/node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -6241,27 +6894,6 @@ } } }, - "node_modules/@wdio/shared-store-service/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@wdio/spec-reporter": { "version": "8.32.4", "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.32.4.tgz", @@ -6302,19 +6934,10 @@ "node": "^16.13 || >=18" } }, - "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@wdio/utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.33.1.tgz", - "integrity": "sha512-W0ArrZbs4M23POv8+FPsgHDFxg+wwklfZgLSsjVq2kpCmBCfIPxKSAOgTo/XrcH4We/OnshgBzxLcI+BHDgi4w==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.35.0.tgz", + "integrity": "sha512-9KCyn4aS+9tWfthnUkNFVe52AM6QrLGAeIxgGxNlzTAcQGl7jjwdDM7aSK0RjLkWI3a/88DRH21mN/t2LGDmPQ==", "dev": true, "dependencies": { "@puppeteer/browsers": "^1.6.0", @@ -6332,7 +6955,19 @@ "wait-port": "^1.0.4" }, "engines": { - "node": "^16.13 || >=18" + "node": "^16.13 || >=18" + } + }, + "node_modules/@wdio/utils/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@webassemblyjs/ast": { @@ -6599,15 +7234,15 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { - "debug": "^4.3.4" + "debug": "4" }, "engines": { - "node": ">= 14" + "node": ">= 6.0.0" } }, "node_modules/aggregate-error": { @@ -6964,6 +7599,15 @@ "ieee754": "^1.2.1" } }, + "node_modules/archiver/node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/archiver/node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7303,9 +7947,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1595.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1595.0.tgz", - "integrity": "sha512-ee0FaplSMz9Y6XJnnyDCHv6SLziJ2YCI4SsO0VRFUKK4Jtk/KErp20CJI/4ZsS+oz7k2/vQ3JqGQXCz95nU8Ww==", + "version": "2.1598.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1598.0.tgz", + "integrity": "sha512-/oPetmY5v62lAt2jTRfIEHrdrg8hfz5KI8qvvP/jhFdNJfLZ85nsn3+fSS8i3FgfeWXIS5yv4ZPpA+JNAnBwdQ==", "hasInstallScript": true, "dependencies": { "buffer": "4.9.2", @@ -7825,12 +8469,12 @@ } }, "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "engines": { - "node": ">=8.0.0" + "node": "*" } }, "node_modules/buffer-equal": { @@ -8013,9 +8657,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001607", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", - "integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==", + "version": "1.0.30001609", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz", + "integrity": "sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA==", "funding": [ { "type": "opencollective", @@ -8031,6 +8675,16 @@ } ] }, + "node_modules/centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "dev": true, + "peer": true, + "dependencies": { + "follow-redirects": "^1.15.6" + } + }, "node_modules/chai": { "version": "4.3.10", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", @@ -8077,6 +8731,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -8172,34 +8838,6 @@ "node": ">=18" } }, - "node_modules/chromedriver/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/chromedriver/node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/chromium-bidi": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz", @@ -8320,12 +8958,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, "node_modules/cli-truncate/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -8359,12 +8991,12 @@ } }, "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, "engines": { - "node": ">= 12" + "node": ">= 10" } }, "node_modules/clipboardy": { @@ -8382,153 +9014,15 @@ "node": ">=8" } }, - "node_modules/clipboardy/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "peer": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/clipboardy/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "peer": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clipboardy/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "peer": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clipboardy/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clipboardy/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "peer": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clipboardy/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/clipboardy/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/clipboardy/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "peer": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clipboardy/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clipboardy/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "peer": true - }, - "node_modules/clipboardy/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", + "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" } }, "node_modules/clone": { @@ -9200,12 +9694,12 @@ "peer": true }, "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "dev": true, "engines": { - "node": ">= 12" + "node": ">= 14" } }, "node_modules/data-urls": { @@ -9304,12 +9798,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9383,9 +9877,9 @@ } }, "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -9716,6 +10210,18 @@ "edgedriver": "bin/edgedriver.js" } }, + "node_modules/edgedriver/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/edgedriver/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -9762,9 +10268,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.730", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.730.tgz", - "integrity": "sha512-oJRPo82XEqtQAobHpJIR3zW5YO3sSRRkPz2an4yxi1UvqhsGm54vR/wzTFV74a3soDOJ8CKW7ajOOX5ESzddwg==" + "version": "1.4.735", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.735.tgz", + "integrity": "sha512-pkYpvwg8VyOTQAeBqZ7jsmpCjko1Qc6We1ZtZCjRyYbT5v4AIUKDy5cQTRotQlSSZmMr8jqpEt6JtOj5k7lR7A==" }, "node_modules/emittery": { "version": "0.13.1", @@ -9778,10 +10284,10 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/emojis-list": { @@ -10393,13 +10899,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "peer": true - }, "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10608,135 +11107,6 @@ "eslint": ">=8.56.0" } }, - "node_modules/eslint-plugin-unicorn/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/eslint-plugin-unicorn/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint-plugin-unused-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.1.0.tgz", @@ -10925,26 +11295,95 @@ } }, "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, + "peer": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "engines": { - "node": ">=16.17" + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "peer": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "peer": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, "node_modules/exif-parser": { @@ -11251,31 +11690,27 @@ } }, "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/figures/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.0" } }, "node_modules/file-entry-cache": { @@ -11504,22 +11939,13 @@ "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", "dev": true, "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fkill-cli/node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, + "escape-string-regexp": "5.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/fkill-cli/node_modules/escape-string-regexp": { @@ -11557,30 +11983,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/fkill-cli/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fkill-cli/node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/fkill-cli/node_modules/fkill": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/fkill/-/fkill-8.1.1.tgz", @@ -11613,15 +12015,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill-cli/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/fkill-cli/node_modules/indent-string": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", @@ -11634,63 +12027,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill-cli/node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fkill-cli/node_modules/inquirer-autocomplete-prompt": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.4.0.tgz", - "integrity": "sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "figures": "^3.2.0", - "run-async": "^2.4.0", - "rxjs": "^6.6.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "inquirer": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/fkill-cli/node_modules/inquirer-autocomplete-prompt/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, "node_modules/fkill-cli/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -11703,21 +12039,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill-cli/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/fkill-cli/node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, "node_modules/fkill-cli/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -11730,21 +12051,6 @@ "node": ">=8" } }, - "node_modules/fkill-cli/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fkill-cli/node_modules/pid-port": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/pid-port/-/pid-port-0.2.0.tgz", @@ -11760,30 +12066,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill-cli/node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/fkill-cli/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/fkill-cli/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/fkill-cli/node_modules/taskkill": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/taskkill/-/taskkill-4.0.0.tgz", @@ -11800,26 +12082,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill-cli/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/fkill-cli/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fkill/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -11855,15 +12117,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/fkill/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -11876,15 +12129,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fkill/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/fkill/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -11897,36 +12141,6 @@ "node": ">=8" } }, - "node_modules/fkill/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fkill/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/fkill/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -12022,6 +12236,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -12132,65 +12358,23 @@ "os": [ "darwin" ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fstream/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fstream/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" }, "engines": { - "node": "*" + "node": ">=0.6" } }, "node_modules/fstream/node_modules/rimraf": { @@ -12287,6 +12471,56 @@ "node": "^16.13 || >=18 || >=20" } }, + "node_modules/geckodriver/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/geckodriver/node_modules/decamelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/geckodriver/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/geckodriver/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/geckodriver/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -12411,15 +12645,16 @@ } }, "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, - "engines": { - "node": ">=16" + "peer": true, + "dependencies": { + "pump": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, "node_modules/get-symbol-description": { @@ -12454,15 +12689,6 @@ "node": ">= 14" } }, - "node_modules/get-uri/node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/gifwrap": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz", @@ -12475,19 +12701,19 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=12" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -12510,6 +12736,26 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", @@ -12892,16 +13138,17 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/http2-wrapper": { @@ -12918,31 +13165,31 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "6", "debug": "4" }, "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "engines": { - "node": ">=16.17.0" + "node": ">=10.17.0" } }, "node_modules/i18next": { - "version": "23.11.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.0.tgz", - "integrity": "sha512-VwFtlgy2LDbY0Qs6VfekIm6mv5/JmSJrtBf4aszl7Vby8+GcBlri0/7dkMZXmzTfiBMPUPBOmYCdQK7K4emkGQ==", + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.1.tgz", + "integrity": "sha512-mXw4A24BiPZKRsbb9ewgSvjYd6fxFCNwJyfK6nYfSTIAX2GkCWcb598m3DFkDZmqADatvuASrKo6qwORz3VwTQ==", "funding": [ { "type": "individual", @@ -13111,43 +13358,68 @@ } }, "node_modules/inquirer": { - "version": "9.2.12", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", - "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, "dependencies": { - "@ljharb/through": "^2.3.11", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^5.0.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", "lodash": "^4.17.21", - "mute-stream": "1.0.0", + "mute-stream": "0.0.8", "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" }, "engines": { - "node": ">=14.18.0" + "node": ">=12.0.0" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/inquirer-autocomplete-prompt": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.4.0.tgz", + "integrity": "sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==", "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "figures": "^3.2.0", + "run-async": "^2.4.0", + "rxjs": "^6.6.2" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=10" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "inquirer": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, + "node_modules/inquirer-autocomplete-prompt/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/inquirer/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -13427,12 +13699,15 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-function": { @@ -13616,15 +13891,13 @@ } }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "dev": true, + "peer": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/is-string": { @@ -13672,12 +13945,12 @@ } }, "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13821,6 +14094,18 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -14072,15 +14357,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-changed-files/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/jest-changed-files/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -14093,15 +14369,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-changed-files/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/jest-changed-files/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -14114,36 +14381,6 @@ "node": ">=8" } }, - "node_modules/jest-changed-files/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/jest-changed-files/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/jest-circus": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", @@ -14253,16 +14490,6 @@ } } }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/jest-config/node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -14278,38 +14505,6 @@ "node": ">=8" } }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -14641,48 +14836,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -14809,21 +14962,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/jimp": { "version": "0.16.13", "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.13.tgz", @@ -14950,66 +15088,6 @@ } } }, - "node_modules/jsdom/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/jsdom/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -15407,18 +15485,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/loglevel": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", @@ -15790,18 +15856,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow/node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/meow/node_modules/read-pkg": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", @@ -15945,15 +15999,12 @@ } }, "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/mimic-response": { @@ -15988,9 +16039,9 @@ } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -16098,43 +16149,24 @@ "engines": { "node": ">= 14.0.0" } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha/node_modules/yargs": { @@ -16155,15 +16187,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/mochawesome": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz", @@ -16238,13 +16261,10 @@ "dev": true }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true }, "node_modules/n12": { "version": "1.8.32", @@ -16425,6 +16445,15 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/node-fetch/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -16473,30 +16502,26 @@ } }, "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "dev": true, + "peer": true, "dependencies": { - "path-key": "^4.0.0" + "path-key": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, + "peer": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, "node_modules/nprogress": { @@ -16667,15 +16692,15 @@ } }, "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "mimic-fn": "^4.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -16724,6 +16749,26 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" }, + "node_modules/openfin-adapter/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/openfin-notifications": { "version": "2.4.0-alpha-3443", "resolved": "https://registry.npmjs.org/openfin-notifications/-/openfin-notifications-2.4.0-alpha-3443.tgz", @@ -16912,18 +16957,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -17010,6 +17043,44 @@ "node": ">= 14" } }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", @@ -17244,12 +17315,17 @@ "dev": true }, "node_modules/phin": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", - "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "centra": "^2.7.0" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/picocolors": { "version": "1.0.0", @@ -17317,15 +17393,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pid-port/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/pid-port/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -17338,15 +17405,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pid-port/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pid-port/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -17359,36 +17417,6 @@ "node": ">=8" } }, - "node_modules/pid-port/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pid-port/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/pid-port/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -17718,15 +17746,15 @@ } }, "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.0.1", "proxy-from-env": "^1.1.0", @@ -17736,6 +17764,44 @@ "node": ">= 14" } }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -17839,15 +17905,41 @@ "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=16.3.0" - }, - "peerDependencies": { - "typescript": ">= 4.7.4" + "node": ">=16.3.0" + }, + "peerDependencies": { + "typescript": ">= 4.7.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/puppeteer-core/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/puppeteer-core/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=12" } }, "node_modules/puppeteer-core/node_modules/devtools-protocol": { @@ -17856,6 +17948,32 @@ "integrity": "sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==", "dev": true }, + "node_modules/puppeteer-core/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/puppeteer-core/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/puppeteer-core/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -17923,6 +18041,15 @@ "node": ">=12" } }, + "node_modules/puppeteer-core/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -18253,229 +18380,132 @@ } }, "node_modules/read-pkg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "dependencies": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^6.0.0", - "parse-json": "^7.0.0", - "type-fest": "^4.2.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/read-pkg-up": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.0.0.tgz", - "integrity": "sha512-jgmKiS//w2Zs+YbX039CorlkOp8FIVbSAN8r8GJHDsGlmNPXo+VeHkqAwCiQVTTx5/LwLZTcEw59z3DvcLbr0g==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { - "find-up": "^6.3.0", - "read-pkg": "^8.0.0", - "type-fest": "^3.12.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">=16" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/read-pkg-up/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "p-locate": "^6.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "yocto-queue": "^1.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "p-limit": "^2.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" } }, "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/read-pkg/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-pkg/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/read-pkg/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "dev": true, - "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/read-pkg/node_modules/parse-json/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "semver": "bin/semver" } }, "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.15.0.tgz", - "integrity": "sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/readable-stream": { @@ -18540,6 +18570,18 @@ "minimatch": "^5.1.0" } }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -18754,6 +18796,25 @@ "node": ">=10" } }, + "node_modules/replace-in-file/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18888,36 +18949,6 @@ "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -18948,49 +18979,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, "engines": { "node": ">=0.12.0" @@ -19209,28 +19201,6 @@ "node": ">= 14.20.0" } }, - "node_modules/selenium-webdriver/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -19454,16 +19424,10 @@ } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/sisteransi": { "version": "1.0.5", @@ -19508,18 +19472,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -19531,9 +19483,9 @@ } }, "node_modules/socks": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", - "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "dependencies": { "ip-address": "^9.0.5", @@ -19558,6 +19510,18 @@ "node": ">= 14" } }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/sortablejs": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", @@ -19755,6 +19719,36 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -19876,15 +19870,12 @@ } }, "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/strip-indent": { @@ -20020,15 +20011,17 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -20170,15 +20163,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/taskkill/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/taskkill/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -20191,21 +20175,6 @@ "node": ">=8" } }, - "node_modules/taskkill/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/taskkill/node_modules/p-finally": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", @@ -20215,21 +20184,6 @@ "node": ">=8" } }, - "node_modules/taskkill/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/taskkill/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/tcomb": { "version": "3.2.29", "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", @@ -20361,23 +20315,9 @@ "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "randombytes": "^2.1.0" } }, "node_modules/terser/node_modules/commander": { @@ -20418,26 +20358,6 @@ "concat-map": "0.0.1" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/test-exclude/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -20703,6 +20623,15 @@ } } }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-loader": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", @@ -20944,9 +20873,9 @@ } }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -21019,8 +20948,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unicorn-magic": { "version": "0.1.0", @@ -21440,115 +21368,6 @@ "node": "^16.13 || >=18" } }, - "node_modules/webdriver/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/webdriver/node_modules/@wdio/config": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.35.0.tgz", - "integrity": "sha512-I36sBPMl/+LCyQ3Pwb8gGQM6KxwmUfhOPp16TxN21Qo/Bc0fZfyGIg6KevmRu4DuqpGUm5MMVSfyPhLUkMk3Cg==", - "dev": true, - "dependencies": { - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.4", - "@wdio/utils": "8.35.0", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.0.0", - "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" - }, - "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/webdriver/node_modules/@wdio/utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.35.0.tgz", - "integrity": "sha512-9KCyn4aS+9tWfthnUkNFVe52AM6QrLGAeIxgGxNlzTAcQGl7jjwdDM7aSK0RjLkWI3a/88DRH21mN/t2LGDmPQ==", - "dev": true, - "dependencies": { - "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.4", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.1.0", - "edgedriver": "^5.3.5", - "geckodriver": "^4.3.1", - "get-port": "^7.0.0", - "import-meta-resolve": "^4.0.0", - "locate-app": "^2.1.0", - "safaridriver": "^0.1.0", - "split2": "^4.2.0", - "wait-port": "^1.0.4" - }, - "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/webdriver/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/webdriver/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/webdriver/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webdriverio": { "version": "8.35.1", "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.35.1.tgz", @@ -21592,79 +21411,6 @@ } } }, - "node_modules/webdriverio/node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/webdriverio/node_modules/@wdio/config": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.35.0.tgz", - "integrity": "sha512-I36sBPMl/+LCyQ3Pwb8gGQM6KxwmUfhOPp16TxN21Qo/Bc0fZfyGIg6KevmRu4DuqpGUm5MMVSfyPhLUkMk3Cg==", - "dev": true, - "dependencies": { - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.4", - "@wdio/utils": "8.35.0", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.0.0", - "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" - }, - "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/webdriverio/node_modules/@wdio/utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.35.0.tgz", - "integrity": "sha512-9KCyn4aS+9tWfthnUkNFVe52AM6QrLGAeIxgGxNlzTAcQGl7jjwdDM7aSK0RjLkWI3a/88DRH21mN/t2LGDmPQ==", - "dev": true, - "dependencies": { - "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.28.0", - "@wdio/types": "8.32.4", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.1.0", - "edgedriver": "^5.3.5", - "geckodriver": "^4.3.1", - "get-port": "^7.0.0", - "import-meta-resolve": "^4.0.0", - "locate-app": "^2.1.0", - "safaridriver": "^0.1.0", - "split2": "^4.2.0", - "wait-port": "^1.0.4" - }, - "engines": { - "node": "^16.13 || >=18" - } - }, - "node_modules/webdriverio/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webdriverio/node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -22073,22 +21819,17 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -22197,12 +21938,12 @@ } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/yargs-unparser": { @@ -22253,6 +21994,29 @@ "node": ">=8" } }, + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -22263,15 +22027,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yauzl/node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 02cf7158dc..f74d51aaa9 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,9 @@ "overrides": { "parse-bmfont-xml": { "xml2js": "0.5.0" + }, + "@openfin/automation-native": { + "phin": "3.7.1" } } } From fc8bbdb09886775c8bb24c6af51b272ce6086c69 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 16:10:32 +0100 Subject: [PATCH 05/10] Update the launch script for workspace v18 --- .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../integrate-with-excel/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../integrate-with-ms365/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/integrate-with-rss/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/integrate-with-snap/scripts/launch.mjs | 193 ++++++++++++------ .../register-with-browser/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/register-with-dock/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/register-with-home/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/register-with-store/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ how-to/use-notifications/scripts/launch.mjs | 193 ++++++++++++------ how-to/use-theming-basic/scripts/launch.mjs | 193 ++++++++++++------ how-to/use-theming/scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../scripts/launch.mjs | 193 ++++++++++++------ .../workspace-platform-starter/CHANGELOG.md | 2 + .../scripts/launch.mjs | 193 ++++++++++++------ 32 files changed, 4032 insertions(+), 1953 deletions(-) diff --git a/how-to/customize-home-templates/scripts/launch.mjs b/how-to/customize-home-templates/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/customize-home-templates/scripts/launch.mjs +++ b/how-to/customize-home-templates/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-server-authentication/scripts/launch.mjs b/how-to/integrate-server-authentication/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-server-authentication/scripts/launch.mjs +++ b/how-to/integrate-server-authentication/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-bloomberg-basic/scripts/launch.mjs b/how-to/integrate-with-bloomberg-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-bloomberg-basic/scripts/launch.mjs +++ b/how-to/integrate-with-bloomberg-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-excel/scripts/launch.mjs b/how-to/integrate-with-excel/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-excel/scripts/launch.mjs +++ b/how-to/integrate-with-excel/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-ms365-basic/scripts/launch.mjs b/how-to/integrate-with-ms365-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-ms365-basic/scripts/launch.mjs +++ b/how-to/integrate-with-ms365-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-ms365-low-code-basic/scripts/launch.mjs b/how-to/integrate-with-ms365-low-code-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-ms365-low-code-basic/scripts/launch.mjs +++ b/how-to/integrate-with-ms365-low-code-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-ms365-low-code/scripts/launch.mjs b/how-to/integrate-with-ms365-low-code/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-ms365-low-code/scripts/launch.mjs +++ b/how-to/integrate-with-ms365-low-code/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-ms365/scripts/launch.mjs b/how-to/integrate-with-ms365/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-ms365/scripts/launch.mjs +++ b/how-to/integrate-with-ms365/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-openid-connect/scripts/launch.mjs b/how-to/integrate-with-openid-connect/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-openid-connect/scripts/launch.mjs +++ b/how-to/integrate-with-openid-connect/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-rss/scripts/launch.mjs b/how-to/integrate-with-rss/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-rss/scripts/launch.mjs +++ b/how-to/integrate-with-rss/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-salesforce-basic/scripts/launch.mjs b/how-to/integrate-with-salesforce-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-salesforce-basic/scripts/launch.mjs +++ b/how-to/integrate-with-salesforce-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-salesforce/scripts/launch.mjs b/how-to/integrate-with-salesforce/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-salesforce/scripts/launch.mjs +++ b/how-to/integrate-with-salesforce/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-servicenow-basic/scripts/launch.mjs b/how-to/integrate-with-servicenow-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-servicenow-basic/scripts/launch.mjs +++ b/how-to/integrate-with-servicenow-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-servicenow/scripts/launch.mjs b/how-to/integrate-with-servicenow/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-servicenow/scripts/launch.mjs +++ b/how-to/integrate-with-servicenow/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-snap-basic/scripts/launch.mjs b/how-to/integrate-with-snap-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-snap-basic/scripts/launch.mjs +++ b/how-to/integrate-with-snap-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/integrate-with-snap/scripts/launch.mjs b/how-to/integrate-with-snap/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/integrate-with-snap/scripts/launch.mjs +++ b/how-to/integrate-with-snap/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-browser/scripts/launch.mjs b/how-to/register-with-browser/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-browser/scripts/launch.mjs +++ b/how-to/register-with-browser/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-dock-basic/scripts/launch.mjs b/how-to/register-with-dock-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-dock-basic/scripts/launch.mjs +++ b/how-to/register-with-dock-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-dock/scripts/launch.mjs b/how-to/register-with-dock/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-dock/scripts/launch.mjs +++ b/how-to/register-with-dock/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-home-basic/scripts/launch.mjs b/how-to/register-with-home-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-home-basic/scripts/launch.mjs +++ b/how-to/register-with-home-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-home/scripts/launch.mjs b/how-to/register-with-home/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-home/scripts/launch.mjs +++ b/how-to/register-with-home/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-platform-windows/scripts/launch.mjs b/how-to/register-with-platform-windows/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-platform-windows/scripts/launch.mjs +++ b/how-to/register-with-platform-windows/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-store-basic/scripts/launch.mjs b/how-to/register-with-store-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-store-basic/scripts/launch.mjs +++ b/how-to/register-with-store-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/register-with-store/scripts/launch.mjs b/how-to/register-with-store/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/register-with-store/scripts/launch.mjs +++ b/how-to/register-with-store/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/support-context-and-intents/scripts/launch.mjs b/how-to/support-context-and-intents/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/support-context-and-intents/scripts/launch.mjs +++ b/how-to/support-context-and-intents/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/use-notifications/scripts/launch.mjs b/how-to/use-notifications/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/use-notifications/scripts/launch.mjs +++ b/how-to/use-notifications/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/use-theming-basic/scripts/launch.mjs b/how-to/use-theming-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/use-theming-basic/scripts/launch.mjs +++ b/how-to/use-theming-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/use-theming/scripts/launch.mjs b/how-to/use-theming/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/use-theming/scripts/launch.mjs +++ b/how-to/use-theming/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/workspace-native-window-integration/scripts/launch.mjs b/how-to/workspace-native-window-integration/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/workspace-native-window-integration/scripts/launch.mjs +++ b/how-to/workspace-native-window-integration/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/workspace-platform-starter-basic/scripts/launch.mjs b/how-to/workspace-platform-starter-basic/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/workspace-platform-starter-basic/scripts/launch.mjs +++ b/how-to/workspace-platform-starter-basic/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index 5b22a15952..b443076b51 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,8 @@ ## v18.0.0 +- npm run launch now launches via the fins link when running on mac instead of the node adapter. +- We now capture the window state when saving a page and apply it if a page is being launched into a new window. - Improvement: Added `apply` as an action on the WorkspaceChangedLifecyclePayload. Previously we had `create`, `update`, `delete`. `update` was being fired when a workspace was updated and when a workspace was applied. `apply` now makes it clear when a particular workspace platform override has been triggered. - Improvement: modules/integrations/workspaces this module now refreshes the entries when a workspace is applied. So if a workspace entry in Home said it was selected it would be updated and the newly selected workspace would be updated to reflect it is the currently selected workspace. - Updated: modules/composite/default-workspace/lifecycle logic to listen out for the new `apply` action. diff --git a/how-to/workspace-platform-starter/scripts/launch.mjs b/how-to/workspace-platform-starter/scripts/launch.mjs index 2aa68a3fc1..49f9b4c9c4 100644 --- a/how-to/workspace-platform-starter/scripts/launch.mjs +++ b/how-to/workspace-platform-starter/scripts/launch.mjs @@ -5,6 +5,7 @@ * Pressing Ctrl+C/Command+C will terminate the application. */ import { connect, launch } from '@openfin/node-adapter'; +import { exec } from 'child_process'; import { setDefaultResultOrder } from 'dns'; /** @@ -13,68 +14,10 @@ import { setDefaultResultOrder } from 'dns'; */ async function run(manifestUrl) { try { - let quitRequested = false; - let quit; - - const fin = await launchFromNode(manifestUrl); - - if (fin) { - const manifest = await fin.System.fetchManifest(manifestUrl); - - if (manifest.platform?.uuid !== undefined) { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling platform quit'); - const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); - await platform.quit(); - } - } catch (err) { - if (err.toString().includes('no longer connected')) { - console.log('Platform no longer connected'); - console.log('Exiting process'); - process.exit(); - } else { - console.error(err); - } - } - }; - console.log(`Wrapped target platform: ${manifest.platform.uuid}`); - } else { - quit = async () => { - try { - if (!quitRequested) { - quitRequested = true; - console.log('Calling application quit'); - const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); - await app.quit(); - } - } catch (err) { - console.error(err); - } - }; - console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); - } - - // do something when app is closing - process.on('exit', async () => { - console.log('Process exit called'); - await quit(); - }); - - // catches ctrl+c event - process.on('SIGINT', async () => { - console.log('Ctrl + C called'); - await quit(); - }); - - console.log(`You successfully connected to the manifest: ${manifestUrl}`); - console.log(`Please wait while the sample loads.`); - console.log(); - console.log(`If using browser use the Quit option from the main menu.`); - console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); - console.log(); + if (process.platform === 'darwin') { + await launchFromFinsLink(manifestUrl); + } else { + await launchFromNodeAdapter(manifestUrl); } } catch (e) { console.error(`Error: Connection failed`); @@ -82,13 +25,137 @@ async function run(manifestUrl) { } } +/** + * Launch the manifest using the node adapter. + * @param manifestUrl the url to launch + */ +async function launchFromNodeAdapter(manifestUrl) { + let quitRequested = false; + let quit; + + const fin = await connectAndGetFinAPI(manifestUrl); + + if (fin) { + const manifest = await fin.System.fetchManifest(manifestUrl); + + if (manifest.platform?.uuid !== undefined) { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling platform quit'); + const platform = fin.Platform.wrapSync({ uuid: manifest.platform.uuid }); + await platform.quit(); + } + } catch (err) { + if (err.toString().includes('no longer connected')) { + console.log('Platform no longer connected'); + console.log('Exiting process'); + process.exit(); + } else { + console.error(err); + } + } + }; + console.log(`Wrapped target platform: ${manifest.platform.uuid}`); + } else { + quit = async () => { + try { + if (!quitRequested) { + quitRequested = true; + console.log('Calling application quit'); + const app = fin.Application.wrapSync({ uuid: manifest.startup_app.uuid }); + await app.quit(); + } + } catch (err) { + console.error(err); + } + }; + console.log(`Wrapped classic app: ${manifest.startup_app.uuid}`); + } + + // do something when app is closing + process.on('exit', async () => { + console.log('Process exit called'); + await quit(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + await quit(); + }); + + console.log(`You successfully connected to the manifest: ${manifestUrl}`); + console.log(`Please wait while the sample loads.`); + console.log(); + console.log(`If using browser use the Quit option from the main menu.`); + console.log(`Otherwise press Ctrl + C (Windows) or Command + C (Mac) to exit and close the sample.`); + console.log(); + } +} + +/** + * Launch the manifest using the node adapter. + * @param manifestUrl The manifest to launch. + */ +async function launchFromFinsLink(manifestUrl) { + console.log(); + console.log(`Launching manifest...`); + console.log(); + const finsLink = manifestUrl.replace('http', 'fin'); + const finsProcess = exec(`open ${finsLink}`); + + /** + * A simple message to inform the user how to quit the platform. + */ + function logQuitMessage() { + console.log(); + console.log('Please quit the platform using:'); + console.log(); + console.log('- Process Manager (https://start.openfin.co/pm)'); + console.log('- the Quit option from the Workspace Browser main menu or Dock.'); + console.log('- run npm run kill to kill all OpenFin processes.'); + console.log(); + console.log(); + } + + finsProcess.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + finsProcess.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + // do something when app is closing + process.on('exit', async () => { + console.log('Please wait for the OpenFin application to launch.'); + logQuitMessage(); + }); + + // catches ctrl+c event + process.on('SIGINT', async () => { + console.log('Ctrl + C called'); + logQuitMessage(); + }); + + finsProcess.on('exit', (code) => { + if (code === 0) { + console.log('Manifest launched successfully'); + } else { + console.log(`Child process exited with code ${code.toString()}`); + } + }); +} + /** * Launch the manifest using the node adapter. * @param manifestUrl The manifest to launch. * @param exitMethod The method to call if the adapter connection exits. * @returns The fin object representing the connection. */ -async function launchFromNode(manifestUrl, exitMethod) { +async function connectAndGetFinAPI(manifestUrl, exitMethod) { try { console.log(`Launching manifest...`); console.log(); From bbbb95ecf78f19e66994e97e869a3de097e9c258 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 16:10:52 +0100 Subject: [PATCH 06/10] Include window state on page save --- .../client/src/framework/platform/browser.ts | 12 +++++++----- .../src/framework/platform/platform-override.ts | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts b/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts index dce6e76b7c..703f832f63 100644 --- a/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts +++ b/how-to/workspace-platform-starter/client/src/framework/platform/browser.ts @@ -302,8 +302,8 @@ export async function getPageForView(view: OpenFin.View): Promise { - let boundsAndState: { bounds?: OpenFin.Bounds; state?: "maximized" | "minimized" | "normal"} | undefined; +): Promise<{ bounds?: OpenFin.Bounds; state?: "maximized" | "minimized" | "normal" } | undefined> { + let boundsAndState: { bounds?: OpenFin.Bounds; state?: "maximized" | "minimized" | "normal" } | undefined; const platform = getCurrentSync(); if (fromStorage) { const page = await platform.Storage.getPage(pageId); @@ -336,8 +336,10 @@ export async function getPageBoundsAndState( if (!isEmpty(windowId)) { const hostWindow = platform.Browser.wrapSync(windowId); - boundsAndState = { bounds: await hostWindow.openfinWindow.getBounds(), - state: await hostWindow.openfinWindow.getState() }; + boundsAndState = { + bounds: await hostWindow.openfinWindow.getBounds(), + state: await hostWindow.openfinWindow.getState() + }; } return boundsAndState; @@ -475,7 +477,7 @@ export async function launchPage( } } - if(!isEmpty(customState)) { + if (!isEmpty(customState)) { newWindowRequest.state = customState; } diff --git a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts index 2d5a1b0430..b8092deb8b 100644 --- a/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts +++ b/how-to/workspace-platform-starter/client/src/framework/platform/platform-override.ts @@ -496,11 +496,11 @@ export function overrideCallback( req.page.customData = {}; } // only set if it hasn't been provided by the caller - if(isEmpty(req.page?.customData?.windowBounds)) { + if (isEmpty(req.page?.customData?.windowBounds)) { req.page.customData.windowBounds = windowBoundsAndState.bounds; } - if(isEmpty(req.page?.customData?.windowState)) { + if (isEmpty(req.page?.customData?.windowState)) { req.page.customData.windowState = windowBoundsAndState.state; } } From bbc263027af39d7a493c02d6aeadb172f99b20e2 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 17:01:46 +0100 Subject: [PATCH 07/10] Remove rspack --- .../workspace-platform-starter/CHANGELOG.md | 1 - .../client/webpack.config.js | 35 +------------------ .../workspace-platform-starter/package.json | 1 - 3 files changed, 1 insertion(+), 36 deletions(-) diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index b443076b51..f989530279 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -7,7 +7,6 @@ - Improvement: Added `apply` as an action on the WorkspaceChangedLifecyclePayload. Previously we had `create`, `update`, `delete`. `update` was being fired when a workspace was updated and when a workspace was applied. `apply` now makes it clear when a particular workspace platform override has been triggered. - Improvement: modules/integrations/workspaces this module now refreshes the entries when a workspace is applied. So if a workspace entry in Home said it was selected it would be updated and the newly selected workspace would be updated to reflect it is the currently selected workspace. - Updated: modules/composite/default-workspace/lifecycle logic to listen out for the new `apply` action. -- Added support for rspack for faster builds. `npm run build-client-rspack` will npx install rspack and use the webpack config file to build the JavaScript from the TypeScript files. It is faster but no type checking is performed so we still recommend doing validated builds using `npm run build` or `npm run build-client`. - Improved performance of switching schemes - Improved performance of computing dock configuration, especially on theme changes. - Breaking Change (if you do not update your manifest): Added modules as an option for platformProvider.interop settings and made the workspace platform starter interop override a module (so you can decide to load it, chain it with other overrides or exclude it). Please see the new document [how to customize your interop broker](./docs/how-to-customize-your-interop-broker.md). If you want the default interop broker to check endpoints to see if a context type should be enriched through an endpoint then you need to add the wps-interop-override module id to the endpoint clients array in the endpointProvider (see the manifest.fin.json as an example). diff --git a/how-to/workspace-platform-starter/client/webpack.config.js b/how-to/workspace-platform-starter/client/webpack.config.js index 141e24a874..b786e2fcef 100644 --- a/how-to/workspace-platform-starter/client/webpack.config.js +++ b/how-to/workspace-platform-starter/client/webpack.config.js @@ -6,45 +6,12 @@ const alias = { 'workspace-platform-starter/utils': path.resolve(__dirname, '../client/src/framework/utils') }; -const request = process.argv; - -let loaderRule = { +const loaderRule = { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }; -if (request.length > 1 && request[1].includes('rspack')) { - console.log( - '-------------------------------------------------------------------------------------------------' - ); - console.log('Using rspack with SWC Loader.'); - console.log( - 'This will transpile TypeScript files to JavaScript but will not perform TypeScript type checking.' - ); - console.log('Use npm run build or npm run build-client if you want the files built with type checking.'); - console.log( - '-------------------------------------------------------------------------------------------------' - ); - loaderRule = { - test: /\.(j|t)s$/, - exclude: [/[\\/]node_modules[\\/]/], - loader: 'builtin:swc-loader', - options: { - sourceMap: true, - jsc: { - parser: { - syntax: 'typescript' - }, - externalHelpers: true - }, - env: { - targets: 'Chrome >= 110' - } - } - }; -} - const configs = [ { entry: './client/src/provider.ts', diff --git a/how-to/workspace-platform-starter/package.json b/how-to/workspace-platform-starter/package.json index 1962390d6c..1e85ee8195 100644 --- a/how-to/workspace-platform-starter/package.json +++ b/how-to/workspace-platform-starter/package.json @@ -9,7 +9,6 @@ "build-server": "tsc --project ./server", "prebuild-client": "node -p \"'// Generated from package.json version at build time. Do not modify directly.\\nexport const PLATFORM_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > client/src/framework/platform/platform-version.ts", "build-client": "npm run prebuild-client && npm run build-client-parallel", - "build-client-rspack": "npm run prebuild-client && npx @rspack/cli --config ./client/webpack.config.js --mode=production", "build-client-parallel": "node scripts/webpack-parallel.mjs ./client/webpack.config.js", "build-client-serial": "webpack build --config ./client/webpack.config.js --mode=production", "build-templates": "webpack build --config ./templates/webpack.config.js --mode=production", From 94a2ffe79fa487b5488be937f539c0b0abb6af63 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 17:58:41 +0100 Subject: [PATCH 08/10] Gave greater control over what is built. --- .../workspace-platform-starter/CHANGELOG.md | 1 + .../client/framework.webpack.config.js | 63 ++ .../client/starter-modules.webpack.config.js | 723 +++++++++++++++++ .../client/webpack.config.js | 753 +----------------- .../docs/how-to-authenticate.md | 2 +- ...how-to-setup-workspace-platform-starter.md | 28 +- .../workspace-platform-starter/package.json | 13 +- .../scripts/webpack-parallel.mjs | 9 +- .../templates/scripts/generate-module.mjs | 7 +- 9 files changed, 839 insertions(+), 760 deletions(-) create mode 100644 how-to/workspace-platform-starter/client/framework.webpack.config.js create mode 100644 how-to/workspace-platform-starter/client/starter-modules.webpack.config.js diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index f989530279..bb21dc875c 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,7 @@ ## v18.0.0 +- Broke up the build process to make it easier to just build your modules. `npm run build` still builds everything and `npm run build-client` still builds all client related code but now if you change framework files you can use `npm run build-framework`, or if you modify our starter modules you can use `npm run build-starter-modules` or if you just want to build your modules (that are listed in webpack.config.js) then you can use `npm run build-client-modules`. This will let you have a much faster build. - npm run launch now launches via the fins link when running on mac instead of the node adapter. - We now capture the window state when saving a page and apply it if a page is being launched into a new window. - Improvement: Added `apply` as an action on the WorkspaceChangedLifecyclePayload. Previously we had `create`, `update`, `delete`. `update` was being fired when a workspace was updated and when a workspace was applied. `apply` now makes it clear when a particular workspace platform override has been triggered. diff --git a/how-to/workspace-platform-starter/client/framework.webpack.config.js b/how-to/workspace-platform-starter/client/framework.webpack.config.js new file mode 100644 index 0000000000..40063e7c41 --- /dev/null +++ b/how-to/workspace-platform-starter/client/framework.webpack.config.js @@ -0,0 +1,63 @@ +/* eslint-disable unicorn/better-regex */ +const path = require('path'); + +const alias = { + 'workspace-platform-starter': path.resolve(__dirname, '../client/src/framework'), + 'workspace-platform-starter/utils': path.resolve(__dirname, '../client/src/framework/utils') +}; + +const loaderRule = { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ +}; + +const configs = [ + { + entry: './client/src/provider.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'provider.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/shell.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'shell.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js') + }, + experiments: { + outputModule: true + } + } +]; + +module.exports = + process.env.WEBPACK_CONFIG_INDEX !== undefined ? configs[process.env.WEBPACK_CONFIG_INDEX] : configs; diff --git a/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js b/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js new file mode 100644 index 0000000000..a5cbe74ce9 --- /dev/null +++ b/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js @@ -0,0 +1,723 @@ +/* eslint-disable unicorn/better-regex */ +const path = require('path'); + +const alias = { + 'workspace-platform-starter': path.resolve(__dirname, '../client/src/framework'), + 'workspace-platform-starter/utils': path.resolve(__dirname, '../client/src/framework/utils') +}; + +const loaderRule = { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ +}; + +const configs = [ + { + entry: './client/src/modules/auth/example/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'example.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'auth') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/local-storage/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'local-storage.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/channel/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'channel.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/inline-apps/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'inline-apps.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/init-options/interop/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'interop.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/init-options/launch-app/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'launch-app.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/log/console/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'console.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'log') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/actions/opacity/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'opacity.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/example-connection-validation/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'example.connection.validation.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/analytics/console/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'console.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'analytics') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/developer/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'developer.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/integrations/apps/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'apps.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/integrations/workspaces/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'workspaces.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/integrations/pages/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'pages.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/about/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'about.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/pages/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'pages.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/windows/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'windows.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/example-context-processor/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'example.context.processor.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/framework/fdc3/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'fdc3.mapper.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'common', 'lib', 'fdc3') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/actions/custom-menu/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'custom-menu.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/auth/openid-connect/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'openid-connect.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'auth') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/endpoint/favorite-local-storage/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'favorite-local-storage.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/actions/favorites-menu/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'favorites-menu.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/include-in-snapshot/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'include-in-snapshot.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/lifecycle/example-notification-service/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'example-notification-service.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'lifecycle') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/init-options/launch-workspace/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'launch-workspace.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/composite/default-workspace/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'default-workspace.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/content-creation/view-position/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'view-position.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'content-creation') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/actions/window-platform/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'window-platform.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/share/pages/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'pages.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'share') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/share/workspaces/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'workspaces.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'share') + }, + experiments: { + outputModule: true + } + }, + { + entry: './client/src/modules/interop-override/wps-interop-override/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'wps-interop-override.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'interop-override') + }, + experiments: { + outputModule: true + } + } +]; + +module.exports = + process.env.WEBPACK_CONFIG_INDEX !== undefined ? configs[process.env.WEBPACK_CONFIG_INDEX] : configs; diff --git a/how-to/workspace-platform-starter/client/webpack.config.js b/how-to/workspace-platform-starter/client/webpack.config.js index b786e2fcef..19bd16fb48 100644 --- a/how-to/workspace-platform-starter/client/webpack.config.js +++ b/how-to/workspace-platform-starter/client/webpack.config.js @@ -1,767 +1,20 @@ /* eslint-disable unicorn/better-regex */ const path = require('path'); +// eslint-disable-next-line no-unused-vars const alias = { 'workspace-platform-starter': path.resolve(__dirname, '../client/src/framework'), 'workspace-platform-starter/utils': path.resolve(__dirname, '../client/src/framework/utils') }; +// eslint-disable-next-line no-unused-vars const loaderRule = { test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }; -const configs = [ - { - entry: './client/src/provider.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'provider.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/shell.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'shell.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/auth/example/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'example.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'auth') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/local-storage/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'local-storage.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/channel/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'channel.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/inline-apps/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'inline-apps.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/init-options/interop/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'interop.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/init-options/launch-app/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'launch-app.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/log/console/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'console.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'log') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/actions/opacity/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'opacity.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/example-connection-validation/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'example.connection.validation.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/analytics/console/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'console.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'analytics') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/developer/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'developer.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/integrations/apps/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'apps.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/integrations/workspaces/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'workspaces.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/integrations/pages/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'pages.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'integrations') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/about/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'about.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/pages/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'pages.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/windows/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'windows.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/example-context-processor/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'example.context.processor.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/framework/fdc3/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'fdc3.mapper.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'common', 'lib', 'fdc3') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/actions/custom-menu/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'custom-menu.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/auth/openid-connect/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'openid-connect.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'auth') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/endpoint/favorite-local-storage/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'favorite-local-storage.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'endpoint') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/actions/favorites-menu/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'favorites-menu.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/include-in-snapshot/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'include-in-snapshot.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/lifecycle/example-notification-service/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'example-notification-service.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'lifecycle') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/init-options/launch-workspace/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'launch-workspace.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'init-options') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/composite/default-workspace/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'default-workspace.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'composite') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/content-creation/view-position/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'view-position.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'content-creation') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/actions/window-platform/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'window-platform.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'actions') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/share/pages/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'pages.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'share') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/share/workspaces/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'workspaces.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'share') - }, - experiments: { - outputModule: true - } - }, - { - entry: './client/src/modules/interop-override/wps-interop-override/index.ts', - devtool: 'source-map', - module: { - rules: [loaderRule] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - alias - }, - externals: { fin: 'fin' }, - output: { - filename: 'wps-interop-override.bundle.js', - library: { - type: 'module' - }, - path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'interop-override') - }, - experiments: { - outputModule: true - } - } -]; +const configs = []; module.exports = process.env.WEBPACK_CONFIG_INDEX !== undefined ? configs[process.env.WEBPACK_CONFIG_INDEX] : configs; diff --git a/how-to/workspace-platform-starter/docs/how-to-authenticate.md b/how-to/workspace-platform-starter/docs/how-to-authenticate.md index 7a8dacf6b8..66e04cc5f7 100644 --- a/how-to/workspace-platform-starter/docs/how-to-authenticate.md +++ b/how-to/workspace-platform-starter/docs/how-to-authenticate.md @@ -43,7 +43,7 @@ We provide a basic example authentication module to give you an idea of how it w This is an example of a module (see [How To Add A Module](./how-to-add-a-module.md)) that has been created and referenced in the authProvider modules array. Each module can be passed data in a format that the specific module understands. -The source for this example module can be found here: [auth-provider.ts](../client/src/modules/auth/example/auth-provider.ts). It is exported from [index.ts](../client/src/modules/auth/example/index.ts) and it is built on it's own via a [webpack](../client/webpack.config.js) entry. +The source for this example module can be found here: [auth-provider.ts](../client/src/modules/auth/example/auth-provider.ts). It is exported from [index.ts](../client/src/modules/auth/example/index.ts) and it is built on it's own via a [webpack](../client/starter-modules.webpack.config.js) entry. This example module is there for you to test different auth flows (e.g. autoLogin) and to give an example of how a module could be built and plugged in. The settings are: diff --git a/how-to/workspace-platform-starter/docs/how-to-setup-workspace-platform-starter.md b/how-to/workspace-platform-starter/docs/how-to-setup-workspace-platform-starter.md index b4b27465b4..d285c8b968 100644 --- a/how-to/workspace-platform-starter/docs/how-to-setup-workspace-platform-starter.md +++ b/how-to/workspace-platform-starter/docs/how-to-setup-workspace-platform-starter.md @@ -52,12 +52,38 @@ This runs the same code with slightly different settings to load an FDC3 directo 7. To launch your store launch the Home UI and use / to show a list of the available commands and select Store. Storefront will be shown and your store will be listed. The [apps](../public/common/apps.json) are displayed as described in their respective files alongside a Storefront configuration setting defined in your [manifest](../public/manifest.fin.json). -8. If you modify the project and want to rebuild. +8. If you modify the project and want to rebuild everything. ```shell npm run build ``` +9. If you modify the [client/src/provider.ts](../client/src/provider.ts), [client/src/shell.ts](../client/src/shell.ts) or anything under [client/src/framework](../client/src/framework) you can build just those files. + +```shell +npm run build-framework +``` + +10. If you modify any of the workspace platform starter modules in [client/src/modules](../client/src/modules) you can rebuild the workspace platform starter modules. + +```shell +npm run build-starter-modules +``` + +11. If you are generating and working on your own modules in [client/src/modules](../client/src/modules) you can rebuild the your modules. + +```shell +npm run build-client-modules +``` + +12. If you have changed the sample server logic in [server/src](../server/src) you can rebuild the just the server. + +```shell +npm run build-server +``` + +You will need to do a complete build at least once. From there you may end up only needing to use `npm run build-client-modules` to quickly build just your modules. + Once you have built the project it is easy to extend through config (either the manifest file or settings returned from a service) and custom JavaScript Modules. The remaining guides will walk you through the process. [<- Back to Table Of Contents](../README.md) diff --git a/how-to/workspace-platform-starter/package.json b/how-to/workspace-platform-starter/package.json index 1e85ee8195..d1bb08df6b 100644 --- a/how-to/workspace-platform-starter/package.json +++ b/how-to/workspace-platform-starter/package.json @@ -8,9 +8,16 @@ "build": "npm run build-server & npm run build-client", "build-server": "tsc --project ./server", "prebuild-client": "node -p \"'// Generated from package.json version at build time. Do not modify directly.\\nexport const PLATFORM_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > client/src/framework/platform/platform-version.ts", - "build-client": "npm run prebuild-client && npm run build-client-parallel", - "build-client-parallel": "node scripts/webpack-parallel.mjs ./client/webpack.config.js", - "build-client-serial": "webpack build --config ./client/webpack.config.js --mode=production", + "build-client": "npm run build-framework && npm run build-starter-modules && npm run build-client-modules", + "build-framework": "npm run prebuild-client && npm run build-framework-parallel", + "build-framework-parallel": "node scripts/webpack-parallel.mjs ./client/framework.webpack.config.js framework", + "build-framework-serial": "webpack build --config ./client/framework.webpack.config.js --mode=production", + "build-client-modules": "npm run build-client-modules-parallel", + "build-client-modules-parallel": "node scripts/webpack-parallel.mjs ./client/webpack.config.js client-modules", + "build-client-modules-serial": "webpack build --config ./client/webpack.config.js --mode=production", + "build-starter-modules": "npm run build-starter-modules-parallel", + "build-starter-modules-parallel": "node scripts/webpack-parallel.mjs ./client/starter-modules.webpack.config.js starter-modules", + "build-starter-modules-serial": "webpack build --config ./client/starter-modules.webpack.config.js --mode=production", "build-templates": "webpack build --config ./templates/webpack.config.js --mode=production", "start": "npm run server", "client": "node ./scripts/launch.mjs", diff --git a/how-to/workspace-platform-starter/scripts/webpack-parallel.mjs b/how-to/workspace-platform-starter/scripts/webpack-parallel.mjs index 575ac9a7a8..6076dbea54 100644 --- a/how-to/workspace-platform-starter/scripts/webpack-parallel.mjs +++ b/how-to/workspace-platform-starter/scripts/webpack-parallel.mjs @@ -6,10 +6,13 @@ import path from 'path'; * Run the process. * @param packageDir The directory for the package json. * @param configFile The config file to read. + * @param buildTarget The build target to use. */ -async function run(packageDir, configFile) { +async function run(packageDir, configFile, buildTarget) { console.log('packagerDir:', packageDir); console.log('configFile:', configFile); + console.log('buildTarget:', buildTarget); + const serialTaskTarget = `build-${buildTarget}-serial`; const fullConfigFilename = path.join(packageDir, configFile); @@ -26,7 +29,7 @@ async function run(packageDir, configFile) { for (let i = chunk * chunkSize; i < Math.min(configModule.default.length, (chunk + 1) * chunkSize); i++) { promises.push( new Promise((resolve, reject) => { - const sp = spawn('npm', ['run', 'build-client-serial'], { + const sp = spawn('npm', ['run', serialTaskTarget], { stdio: 'inherit', env: { ...process.env, WEBPACK_CONFIG_INDEX: i }, shell: true @@ -51,4 +54,4 @@ async function run(packageDir, configFile) { } } -run(path.resolve(path.join(path.dirname(process.argv[1]), '..')), process.argv[2]); +run(path.resolve(path.join(path.dirname(process.argv[1]), '..')), process.argv[2], process.argv[3]); diff --git a/how-to/workspace-platform-starter/templates/scripts/generate-module.mjs b/how-to/workspace-platform-starter/templates/scripts/generate-module.mjs index 8febeebcda..c62f187a28 100644 --- a/how-to/workspace-platform-starter/templates/scripts/generate-module.mjs +++ b/how-to/workspace-platform-starter/templates/scripts/generate-module.mjs @@ -185,8 +185,11 @@ async function addWebPackEntry(moduleOutputDir, kebabType, kebabName) { // eslint-disable-next-line no-div-regex const entriesRegEx = /= \[([\S\s]*)];/; let entries = entriesRegEx.exec(webPackConfig)[1].trim(); - entries += `, - { + if (entries.length > 0) { + entries += `, + `; + } + entries += `{ entry: './${path.relative('.', path.join(moduleOutputDir, 'index.ts')).replace(/\\/g, '/')}', devtool: 'source-map', module: { From 6592b9798bf0b3c13b188b580ce0ad7233ccc361 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2024 20:56:59 +0100 Subject: [PATCH 09/10] Added Cloud Interop support with documentation. --- how-to/support-context-and-intents/README.md | 12 + .../client/src/interopbroker.ts | 824 +++++++++--------- .../client/src/provider.ts | 15 +- .../client/src/shapes.ts | 22 + .../support-context-and-intents/package.json | 1 + .../public/manifest.fin.json | 12 + .../public/second.manifest.fin.json | 12 + .../workspace-platform-starter/CHANGELOG.md | 1 + how-to/workspace-platform-starter/README.md | 1 + .../openfin-cloud-interop/index.ts | 9 + .../openfin-cloud-interop/interop-override.ts | 97 +++ .../openfin-cloud-interop/shapes.ts | 10 + .../client/starter-modules.webpack.config.js | 22 + ...dd-cloud-interop-to-your-interop-broker.md | 61 ++ .../how-to-customize-your-interop-broker.md | 8 +- .../workspace-platform-starter/package.json | 1 + .../public/manifest.fin.json | 16 + .../public/settings.json | 16 + package-lock.json | 390 ++++++++- 19 files changed, 1095 insertions(+), 435 deletions(-) create mode 100644 how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/index.ts create mode 100644 how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/interop-override.ts create mode 100644 how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/shapes.ts create mode 100644 how-to/workspace-platform-starter/docs/how-to-add-cloud-interop-to-your-interop-broker.md diff --git a/how-to/support-context-and-intents/README.md b/how-to/support-context-and-intents/README.md index 59b6d29f8a..aea181a028 100644 --- a/how-to/support-context-and-intents/README.md +++ b/how-to/support-context-and-intents/README.md @@ -8,6 +8,7 @@ This sample covers: - Supporting Interop/FDC3 Context messages - Supporting Interop/FDC3 Intents +- Optionally supporting OpenFin Cloud Interop for context sharing: - Using a golden data source (in [apps](./public/common/) apps\*.json) to drive the apps that show up in Home and in intent resolution - Customization through config (in the [manifest.fin.json](public/manifest.fin.json) file) @@ -71,6 +72,8 @@ This runs the same code with slightly different settings to show a different the npm run build ``` +8. If you wish to test Cloud Interop so that you can launch the two platforms and see them communicating via the cloud then please contact your OpenFin sales account manager to get your connection information. Once you have that you can update the cloudInteropProvider settings in the [manifest](public/manifest.fin.json) and/or [second.manifest.fin.json](public/second.manifest.fin.json). Once enabled you will be able to share context across user channels between platforms regardless of whether they are running on the same machine or not. + ## How it works The Server in this example provides two sets of content over HTTP GET. @@ -105,6 +108,15 @@ Intent support is added to the sample in the following ways: - Update [apps.json](./public/common/apps.json) to add the new views/pages and specify that they support intents in their metadata. - Update [apps.ts](client/src/apps.ts) to support getting apps that support intents or context types. +# Cloud Interop Support implemented? + +Adding cloud interop support is very simple. + +- We npm install [@openfin/cloud-interop](https://www.npmjs.com/package/@openfin/cloud-interop) +- We provide a way of providing cloud interop configuration through a manifest (in a real application you should be fetching this information from a service). +- We pass the settings to the cloudInteropOverride function provided by the @openfin/cloud-interop library. +- We add the initialized cloudInteropOverride to the interopOverride array that is set as part of your [platform's initialization](./client/src/provider.ts). + ## Using the Sample To run this sample: diff --git a/how-to/support-context-and-intents/client/src/interopbroker.ts b/how-to/support-context-and-intents/client/src/interopbroker.ts index ed87e0a100..6822c0444e 100644 --- a/how-to/support-context-and-intents/client/src/interopbroker.ts +++ b/how-to/support-context-and-intents/client/src/interopbroker.ts @@ -15,355 +15,400 @@ const RESOLVER_TIMEOUT = "ResolverTimeout"; /** * Create an override for the platform interop. * @param customSettings Custom settings to initialize the platform. - * @param InteropBroker The interop broker base type to derive from. * @returns The override for the interop broker. */ export function createInteropOverride( - customSettings: CustomSettings, - InteropBroker: OpenFin.Constructor -): OpenFin.InteropBroker { - /** - * Override the InteropBroken class. - */ - class InteropOverride extends InteropBroker { + customSettings: CustomSettings +): OpenFin.ConstructorOverride { + return (Base: OpenFin.Constructor) => /** - * Launch an applications with a specific intent. - * @param app The app to launch. - * @param intent The intent to launch the app with. - * @returns The source and version of the app that was launched if there was one. + * In Interop Broker Implementation that supports fdc3 1.2 */ - public async launchAppWithIntent( - app: App, - intent: OpenFin.Intent - ): Promise< - | { - source: string; - version?: string; - } - | undefined - > { - console.log("Launching app with intent."); - - if ( - app.manifestType !== "view" && - app.manifestType !== "inline-view" && - app.manifestType !== "snapshot" - ) { - // optional logic show a prompt to the user to let them know - console.warn("Unable to raise intent against app as only view/snapshot based apps are supported."); - return; - } - - if (app.manifestType === "view" || app.manifestType === "inline-view") { - console.log(`The supporting app is a view (${app.manifestType})`); - - const identity = await launchView(app); - if (!identity) { + class InteropOverride extends Base { + /** + * Launch an applications with a specific intent. + * @param app The app to launch. + * @param intent The intent to launch the app with. + * @returns The source and version of the app that was launched if there was one. + */ + public async launchAppWithIntent( + app: App, + intent: OpenFin.Intent + ): Promise< + | { + source: string; + version?: string; + } + | undefined + > { + console.log("Launching app with intent."); + + if ( + app.manifestType !== "view" && + app.manifestType !== "inline-view" && + app.manifestType !== "snapshot" + ) { // optional logic show a prompt to the user to let them know - console.warn("Unable to raise intent against view as no identity was returned."); + console.warn("Unable to raise intent against app as only view/snapshot based apps are supported."); return; } - await super.setIntentTarget(intent, identity); - } - if (app.manifestType === "snapshot") { - console.log("The supporting app is a view."); + if (app.manifestType === "view" || app.manifestType === "inline-view") { + console.log(`The supporting app is a view (${app.manifestType})`); - const identities = await launchSnapshot(app); - if (!identities) { - // optional logic show a prompt to the user to let them know - console.warn("Unable to raise intent against target as no identity was returned."); - return; - } - for (const identity of identities) { + const identity = await launchView(app); + if (!identity) { + // optional logic show a prompt to the user to let them know + console.warn("Unable to raise intent against view as no identity was returned."); + return; + } await super.setIntentTarget(intent, identity); } - } - return { - source: app.appId, - version: app.version - }; - } + if (app.manifestType === "snapshot") { + console.log("The supporting app is a view."); - /** - * Get the target identity of the requested app. - * @param appId The app id to get the target for. - * @returns The identity of the target app. - */ - public async getTargetIdentity(appId: string | undefined): Promise { - if (!appId) { - return; - } - const passedIdentity = appId.split("@"); - const name = passedIdentity[0]; - let uuid = fin.me.identity.uuid; - if (passedIdentity.length === 2) { - uuid = passedIdentity[1]; - } - const resolvedIdentity = { uuid, name }; + const identities = await launchSnapshot(app); + if (!identities) { + // optional logic show a prompt to the user to let them know + console.warn("Unable to raise intent against target as no identity was returned."); + return; + } + for (const identity of identities) { + await super.setIntentTarget(intent, identity); + } + } - try { - const targetView = await fin.View.wrap({ uuid, name }); - await targetView.getInfo(); - // passed identity found - return resolvedIdentity; - } catch { - // passed identity does not exist + return { + source: app.appId, + version: app.version + }; } - } - /** - * Launch a picker to chose an application for an intent. - * @param launchOptions The launch options for the app. - * @param launchOptions.apps The optional list of apps to display. - * @param launchOptions.intent The optional intent to support. - * @param launchOptions.intents The optional intents to pick from. - * @returns The picked app. - */ - public async launchAppPicker(launchOptions: { - apps?: App[]; - intent?: Partial; - intents?: { intent: Partial; apps: App[] }[]; - }): Promise< - | { - appId: string; - intent: Partial; - } - | undefined - > { - // show menu - // launch a new window and optionally pass the available intents as customData.apps as part of the window options - // the window can then use raiseIntent against a specific app (the selected one). This is a very basic example. - const height = customSettings?.platformProvider?.intentPicker?.height ?? 400; - const width = customSettings?.platformProvider?.intentPicker?.width ?? 400; - - // this logic runs in the provider so we are using it as a way of determining the root (so it works with root hosting and subdirectory based hosting if a url is not provided) - const url = - customSettings?.platformProvider?.intentPicker?.url ?? - "http://localhost:8080/common/windows/intents/picker.html"; - - const winOption: OpenFin.WindowCreationOptions = { - name: "intent-picker", - includeInSnapshots: false, - fdc3InteropApi: "1.2", - defaultWidth: width, - defaultHeight: height, - showTaskbarIcon: false, - saveWindowState: false, - defaultCentered: true, - customData: { - apps: launchOptions.apps, - intent: launchOptions.intent, - intents: launchOptions.intents - }, - url, - frame: false, - autoShow: true, - alwaysOnTop: true - }; - - const win = await fin.Window.create(winOption); - const webWindow = win.getWebWindow(); - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const getIntentSelection = (webWindow as any).getIntentSelection; + /** + * Get the target identity of the requested app. + * @param appId The app id to get the target for. + * @returns The identity of the target app. + */ + public async getTargetIdentity(appId: string | undefined): Promise { + if (!appId) { + return; + } + const passedIdentity = appId.split("@"); + const name = passedIdentity[0]; + let uuid = fin.me.identity.uuid; + if (passedIdentity.length === 2) { + uuid = passedIdentity[1]; + } + const resolvedIdentity = { uuid, name }; - if (getIntentSelection) { - const selectedAppId = await getIntentSelection(); - return selectedAppId as { - appId: string; - intent: AppIntent; - }; + try { + const targetView = await fin.View.wrap({ uuid, name }); + await targetView.getInfo(); + // passed identity found + return resolvedIdentity; + } catch { + // passed identity does not exist } - } catch { - console.error("App for intent not selected/launched.", launchOptions.intent); } - } - - /** - * Is the connection for the specific identity authorized. - * @param identity The identity of the connection to check. - * @param payload The optional payload. - * @returns True if the connection is authorized. - */ - public async isConnectionAuthorized(identity: OpenFin.Identity, payload?: unknown): Promise { - console.log("Interop connection being made by the following identity with payload:", identity, payload); - // perform connection validation checks here if required and return false if it shouldn't be allowed. - return true; - } - /** - * Is the action authorized. - * @param action The action to test for being authorized. - * @param payload The payload to use in the test. - * @param identity The identity of the client being asked about the action. - * @returns True if the action is authorized. - */ - public async isActionAuthorized( - action: string, - payload: unknown, - identity: OpenFin.ClientIdentity - ): Promise { - console.log("Interop Broker is action authorized:", action, payload, identity); - // perform check here if you wish and return true/false accordingly - return true; - } - - /** - * Get the information for the intents by context. - * @param context The context to get the information for. - * @param context.type The type of the context. - * @param clientIdentity The identity of the client to get the information from. - * @returns The information about the intents for the context. - */ - public async handleInfoForIntentsByContext( - context: { type: string }, - clientIdentity: OpenFin.Identity - ): Promise< - { - intent: { name: string; displayName: string }; - apps: { name: string; appId: string; title: string }[]; - }[] - > { - const intents = await getIntentsByContext(customSettings?.appProvider, context.type); - - if (intents.length === 0) { - throw new Error(NO_APPS_FOUND); + /** + * Launch a picker to chose an application for an intent. + * @param launchOptions The launch options for the app. + * @param launchOptions.apps The optional list of apps to display. + * @param launchOptions.intent The optional intent to support. + * @param launchOptions.intents The optional intents to pick from. + * @returns The picked app. + */ + public async launchAppPicker(launchOptions: { + apps?: App[]; + intent?: Partial; + intents?: { intent: Partial; apps: App[] }[]; + }): Promise< + | { + appId: string; + intent: Partial; + } + | undefined + > { + // show menu + // launch a new window and optionally pass the available intents as customData.apps as part of the window options + // the window can then use raiseIntent against a specific app (the selected one). This is a very basic example. + const height = customSettings?.platformProvider?.intentPicker?.height ?? 400; + const width = customSettings?.platformProvider?.intentPicker?.width ?? 400; + + // this logic runs in the provider so we are using it as a way of determining the root (so it works with root hosting and subdirectory based hosting if a url is not provided) + const url = + customSettings?.platformProvider?.intentPicker?.url ?? + "http://localhost:8080/common/windows/intents/picker.html"; + + const winOption: OpenFin.WindowCreationOptions = { + name: "intent-picker", + includeInSnapshots: false, + fdc3InteropApi: "1.2", + defaultWidth: width, + defaultHeight: height, + showTaskbarIcon: false, + saveWindowState: false, + defaultCentered: true, + customData: { + apps: launchOptions.apps, + intent: launchOptions.intent, + intents: launchOptions.intents + }, + url, + frame: false, + autoShow: true, + alwaysOnTop: true + }; + + const win = await fin.Window.create(winOption); + const webWindow = win.getWebWindow(); + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const getIntentSelection = (webWindow as any).getIntentSelection; + + if (getIntentSelection) { + const selectedAppId = await getIntentSelection(); + return selectedAppId as { + appId: string; + intent: AppIntent; + }; + } + } catch { + console.error("App for intent not selected/launched.", launchOptions.intent); + } } - return intents.map((entry) => ({ - intent: entry.intent, - apps: entry.apps.map((app) => ({ - name: app.appId, - appId: app.appId, - title: app.title - })) - })); - } + /** + * Is the connection for the specific identity authorized. + * @param identity The identity of the connection to check. + * @param payload The optional payload. + * @returns True if the connection is authorized. + */ + public async isConnectionAuthorized(identity: OpenFin.Identity, payload?: unknown): Promise { + console.log( + "Interop connection being made by the following identity with payload:", + identity, + payload + ); + // perform connection validation checks here if required and return false if it shouldn't be allowed. + return true; + } - /** - * Get the information for the apps by intent. - * @param intentOptions The options for the intent. - * @param intentOptions.name The name of the intent. - * @param intentOptions.context The optional context for the intent. - * @param intentOptions.context.type The context type. - * @param clientIdentity The client identity to get the information from. - * @returns The information about the intents for the context. - */ - public async handleInfoForIntent( - intentOptions: { name: string; context?: { type: string } }, - clientIdentity: OpenFin.Identity - ): Promise<{ - intent: { name: string; displayName: string }; - apps: { name: string; appId: string; title: string }[]; - }> { - const result = await getIntent( - customSettings?.appProvider, - intentOptions.name, - intentOptions.context?.type - ); - if (!result) { - throw new Error(NO_APPS_FOUND); + /** + * Is the action authorized. + * @param action The action to test for being authorized. + * @param payload The payload to use in the test. + * @param identity The identity of the client being asked about the action. + * @returns True if the action is authorized. + */ + public async isActionAuthorized( + action: string, + payload: unknown, + identity: OpenFin.ClientIdentity + ): Promise { + console.log("Interop Broker is action authorized:", action, payload, identity); + // perform check here if you wish and return true/false accordingly + return true; } - return { - intent: result.intent, - apps: result.apps.map((app) => { - const appEntry = { + /** + * Get the information for the intents by context. + * @param context The context to get the information for. + * @param context.type The type of the context. + * @param clientIdentity The identity of the client to get the information from. + * @returns The information about the intents for the context. + */ + public async handleInfoForIntentsByContext( + context: { type: string }, + clientIdentity: OpenFin.Identity + ): Promise< + { + intent: { name: string; displayName: string }; + apps: { name: string; appId: string; title: string }[]; + }[] + > { + const intents = await getIntentsByContext(customSettings?.appProvider, context.type); + + if (intents.length === 0) { + throw new Error(NO_APPS_FOUND); + } + + return intents.map((entry) => ({ + intent: entry.intent, + apps: entry.apps.map((app) => ({ name: app.appId, appId: app.appId, title: app.title - }; - return appEntry; - }) - }; - } - - /** - * Handle and intent for the fired context. - * @param contextForIntent The context for the intent. - * @param contextForIntent.type Tht type of the context. - * @param contextForIntent.metadata The metadata for the context. - * @param contextForIntent.metadata.target The optional target for the context. - * @param clientIdentity The identity of the client to handle the intent. - * @returns The application details for the app that handled the intent. - */ - public async handleFiredIntentForContext( - contextForIntent: { type: string; metadata?: { target?: string } }, - clientIdentity: OpenFin.Identity - ): Promise< - | { - source: string; - version?: string; - } - | undefined - > { - const availableIntents = await getIntentsByContext(customSettings?.appProvider, contextForIntent.type); - if (availableIntents.length === 0) { - throw new Error(NO_APPS_FOUND); - } - const intent: OpenFin.Intent & { displayName?: string } = { - context: contextForIntent, - name: "", - displayName: undefined - }; - let targetApp: App | undefined; - let targetAppIntent; - let targetAppIntentCount = 0; - - if (contextForIntent.metadata?.target !== undefined) { - targetApp = await getApp(customSettings?.appProvider, contextForIntent.metadata?.target); + })) + })); } - if (targetApp !== undefined && Array.isArray(targetApp.intents)) { - for (const element of targetApp.intents) { - targetAppIntent = element; - if ( - Array.isArray(targetAppIntent.contexts) && - targetAppIntent.contexts.includes(contextForIntent.type) - ) { - targetAppIntentCount++; - } + /** + * Get the information for the apps by intent. + * @param intentOptions The options for the intent. + * @param intentOptions.name The name of the intent. + * @param intentOptions.context The optional context for the intent. + * @param intentOptions.context.type The context type. + * @param clientIdentity The client identity to get the information from. + * @returns The information about the intents for the context. + */ + public async handleInfoForIntent( + intentOptions: { name: string; context?: { type: string } }, + clientIdentity: OpenFin.Identity + ): Promise<{ + intent: { name: string; displayName: string }; + apps: { name: string; appId: string; title: string }[]; + }> { + const result = await getIntent( + customSettings?.appProvider, + intentOptions.name, + intentOptions.context?.type + ); + if (!result) { + throw new Error(NO_APPS_FOUND); } + + return { + intent: result.intent, + apps: result.apps.map((app) => { + const appEntry = { + name: app.appId, + appId: app.appId, + title: app.title + }; + return appEntry; + }) + }; } - if (targetApp !== undefined && targetAppIntent !== undefined && targetAppIntentCount === 1) { - // a preferred name for an app was given with the context object - // the app existed and it supported the context type and there was only one intent that supported - // that context type. Launch the app with that intent otherwise present the user with a list of - // everything that supports that context type - intent.name = targetAppIntent.name; - intent.displayName = targetAppIntent.name; - const intentResolver = await this.launchAppWithIntent(targetApp, intent); - if (!intentResolver) { + /** + * Handle and intent for the fired context. + * @param contextForIntent The context for the intent. + * @param contextForIntent.type Tht type of the context. + * @param contextForIntent.metadata The metadata for the context. + * @param contextForIntent.metadata.target The optional target for the context. + * @param clientIdentity The identity of the client to handle the intent. + * @returns The application details for the app that handled the intent. + */ + public async handleFiredIntentForContext( + contextForIntent: { type: string; metadata?: { target?: string } }, + clientIdentity: OpenFin.Identity + ): Promise< + | { + source: string; + version?: string; + } + | undefined + > { + const availableIntents = await getIntentsByContext( + customSettings?.appProvider, + contextForIntent.type + ); + if (availableIntents.length === 0) { throw new Error(NO_APPS_FOUND); } - return intentResolver; - } + const intent: OpenFin.Intent & { displayName?: string } = { + context: contextForIntent, + name: "", + displayName: undefined + }; + let targetApp: App | undefined; + let targetAppIntent; + let targetAppIntentCount = 0; + + if (contextForIntent.metadata?.target !== undefined) { + targetApp = await getApp(customSettings?.appProvider, contextForIntent.metadata?.target); + } - if (availableIntents.length === 1) { - intent.name = availableIntents[0].intent.name; - intent.displayName = availableIntents[0].intent.name; - if (availableIntents[0].apps.length === 1) { - const intentResolver = await this.launchAppWithIntent(availableIntents[0].apps[0], intent); + if (targetApp !== undefined && Array.isArray(targetApp.intents)) { + for (const element of targetApp.intents) { + targetAppIntent = element; + if ( + Array.isArray(targetAppIntent.contexts) && + targetAppIntent.contexts.includes(contextForIntent.type) + ) { + targetAppIntentCount++; + } + } + } + + if (targetApp !== undefined && targetAppIntent !== undefined && targetAppIntentCount === 1) { + // a preferred name for an app was given with the context object + // the app existed and it supported the context type and there was only one intent that supported + // that context type. Launch the app with that intent otherwise present the user with a list of + // everything that supports that context type + intent.name = targetAppIntent.name; + intent.displayName = targetAppIntent.name; + const intentResolver = await this.launchAppWithIntent(targetApp, intent); if (!intentResolver) { throw new Error(NO_APPS_FOUND); } return intentResolver; } - if (availableIntents[0].apps.length > 1) { + + if (availableIntents.length === 1) { + intent.name = availableIntents[0].intent.name; + intent.displayName = availableIntents[0].intent.name; + if (availableIntents[0].apps.length === 1) { + const intentResolver = await this.launchAppWithIntent(availableIntents[0].apps[0], intent); + if (!intentResolver) { + throw new Error(NO_APPS_FOUND); + } + return intentResolver; + } + if (availableIntents[0].apps.length > 1) { + try { + const userSelection = await this.launchAppPicker({ + apps: availableIntents[0].apps, + intent + }); + + if (userSelection) { + const selectedApp = availableIntents[0].apps.find( + (entry) => entry.appId === userSelection.appId && entry.appId !== undefined + ); + if (selectedApp) { + const intentResolver = await this.launchAppWithIntent(selectedApp, intent); + if (!intentResolver) { + throw new Error(NO_APPS_FOUND); + } + return intentResolver; + } + } + console.error("We were returned a non existent appId to launch with the intent."); + throw new Error(NO_APPS_FOUND); + } catch { + console.error("App for intent by context not selected/launched.", intent); + throw new Error(RESOLVER_TIMEOUT); + } + } + } else { try { const userSelection = await this.launchAppPicker({ - apps: availableIntents[0].apps, - intent + intent, + intents: availableIntents }); if (userSelection) { - const selectedApp = availableIntents[0].apps.find( + const selectedIntent = availableIntents.find( + (entry) => entry.intent.name === userSelection.intent.name + ); + + if (selectedIntent === undefined) { + console.error( + "The user selected an intent but it's name doesn't match the available intents.", + userSelection + ); + throw new Error(NO_APPS_FOUND); + } + const selectedApp = selectedIntent.apps.find( (entry) => entry.appId === userSelection.appId && entry.appId !== undefined ); if (selectedApp) { + intent.displayName = userSelection.intent.displayName; + intent.name = userSelection.intent?.name ?? ""; const intentResolver = await this.launchAppWithIntent(selectedApp, intent); if (!intentResolver) { throw new Error(NO_APPS_FOUND); @@ -378,132 +423,91 @@ export function createInteropOverride( throw new Error(RESOLVER_TIMEOUT); } } - } else { - try { - const userSelection = await this.launchAppPicker({ - intent, - intents: availableIntents - }); - - if (userSelection) { - const selectedIntent = availableIntents.find( - (entry) => entry.intent.name === userSelection.intent.name - ); + } - if (selectedIntent === undefined) { - console.error( - "The user selected an intent but it's name doesn't match the available intents.", - userSelection + /** + * Handle an intent that was fired. + * @param intent The intent that was fired. + * @returns The source and version of the application that was opened. + */ + public async handleFiredIntent(intent: OpenFin.Intent): Promise< + | { + source: string; + version?: string; + } + | undefined + > { + console.log("Received request for a raised intent:", intent); + let intentApps = await getAppsByIntent(customSettings?.appProvider, intent.name); + let targetApp: App | undefined; + + if (intent.metadata?.target) { + targetApp = await getApp(customSettings?.appProvider, intent.metadata.target as string); + if (targetApp === undefined) { + // check to see if you have been passed a specific identity for a view that should be targeted instead of an app + const targetIdentity = await this.getTargetIdentity(intent.metadata?.target as string); + if (targetIdentity) { + console.log( + "We were passed a view identity instead of an app entry when raising/firing an intent. We will fire the intent at that as it exists and no app entry exists with that name.:", + targetIdentity, + intent ); - throw new Error(NO_APPS_FOUND); - } - const selectedApp = selectedIntent.apps.find( - (entry) => entry.appId === userSelection.appId && entry.appId !== undefined - ); - if (selectedApp) { - intent.displayName = userSelection.intent.displayName; - intent.name = userSelection.intent?.name ?? ""; - const intentResolver = await this.launchAppWithIntent(selectedApp, intent); - if (!intentResolver) { - throw new Error(NO_APPS_FOUND); - } - return intentResolver; + await super.setIntentTarget(intent, targetIdentity); + return { + source: targetIdentity.name + }; } } - console.error("We were returned a non existent appId to launch with the intent."); - throw new Error(NO_APPS_FOUND); - } catch { - console.error("App for intent by context not selected/launched.", intent); - throw new Error(RESOLVER_TIMEOUT); - } - } - } - - /** - * Handle an intent that was fired. - * @param intent The intent that was fired. - * @returns The source and version of the application that was opened. - */ - public async handleFiredIntent(intent: OpenFin.Intent): Promise< - | { - source: string; - version?: string; - } - | undefined - > { - console.log("Received request for a raised intent:", intent); - let intentApps = await getAppsByIntent(customSettings?.appProvider, intent.name); - let targetApp: App | undefined; - - if (intent.metadata?.target) { - targetApp = await getApp(customSettings?.appProvider, intent.metadata.target as string); - if (targetApp === undefined) { - // check to see if you have been passed a specific identity for a view that should be targeted instead of an app - const targetIdentity = await this.getTargetIdentity(intent.metadata?.target as string); - if (targetIdentity) { - console.log( - "We were passed a view identity instead of an app entry when raising/firing an intent. We will fire the intent at that as it exists and no app entry exists with that name.:", - targetIdentity, - intent - ); - await super.setIntentTarget(intent, targetIdentity); - return { - source: targetIdentity.name - }; - } } - } - - if (intentApps.length === 0) { - console.log("No apps support this intent."); - throw new Error(NO_APPS_FOUND); - } - - if (targetApp !== undefined && intentApps.includes(targetApp)) { - console.log("Assigning selected application with intent.", intent); - intentApps = [targetApp]; - } - if (intentApps.length === 1) { - // handle single entry - const intentResolver = await this.launchAppWithIntent(intentApps[0], intent); - if (!intentResolver) { + if (intentApps.length === 0) { + console.log("No apps support this intent."); throw new Error(NO_APPS_FOUND); } - return intentResolver; - } - // show menu - // launch a new window and optionally pass the available intents as customData.apps as part of the window options - // the window can then use raiseIntent against a specific app (the selected one). This is a very basic example. - try { - const userSelection = await this.launchAppPicker({ - apps: intentApps, - intent - }); - if (intentApps === undefined) { - console.warn("We should have a list of apps to search from."); - intentApps = []; + + if (targetApp !== undefined && intentApps.includes(targetApp)) { + console.log("Assigning selected application with intent.", intent); + intentApps = [targetApp]; } - const selectedApp = intentApps.find( - (entry) => entry.appId === userSelection?.appId && entry.appId !== undefined - ); - if (selectedApp) { - const intentResolver = await this.launchAppWithIntent(selectedApp, intent); + + if (intentApps.length === 1) { + // handle single entry + const intentResolver = await this.launchAppWithIntent(intentApps[0], intent); if (!intentResolver) { throw new Error(NO_APPS_FOUND); } return intentResolver; } - console.error("We were returned a non existent appId to launch with the intent."); - throw new Error(NO_APPS_FOUND); - } catch { - console.error("App for intent not selected/launched.", intent); - throw new Error(RESOLVER_TIMEOUT); + // show menu + // launch a new window and optionally pass the available intents as customData.apps as part of the window options + // the window can then use raiseIntent against a specific app (the selected one). This is a very basic example. + try { + const userSelection = await this.launchAppPicker({ + apps: intentApps, + intent + }); + if (intentApps === undefined) { + console.warn("We should have a list of apps to search from."); + intentApps = []; + } + const selectedApp = intentApps.find( + (entry) => entry.appId === userSelection?.appId && entry.appId !== undefined + ); + if (selectedApp) { + const intentResolver = await this.launchAppWithIntent(selectedApp, intent); + if (!intentResolver) { + throw new Error(NO_APPS_FOUND); + } + return intentResolver; + } + console.error("We were returned a non existent appId to launch with the intent."); + throw new Error(NO_APPS_FOUND); + } catch { + console.error("App for intent not selected/launched.", intent); + throw new Error(RESOLVER_TIMEOUT); + } } - } - } - - return new InteropOverride(); + }; } /** diff --git a/how-to/support-context-and-intents/client/src/provider.ts b/how-to/support-context-and-intents/client/src/provider.ts index bc129fb72c..61ea48f996 100644 --- a/how-to/support-context-and-intents/client/src/provider.ts +++ b/how-to/support-context-and-intents/client/src/provider.ts @@ -1,3 +1,4 @@ +import { cloudInteropOverride } from "@openfin/cloud-interop"; import type OpenFin from "@openfin/core"; import { CLITemplate, Home, type App, type HomeSearchListenerRequest } from "@openfin/workspace"; import { init } from "@openfin/workspace-platform"; @@ -28,6 +29,18 @@ window.addEventListener("DOMContentLoaded", async () => { */ async function initializeWorkspacePlatform(customSettings: CustomSettings): Promise { console.log("Initializing workspace platform"); + + const defaultBroker = createInteropOverride(customSettings); + const interopOverride: OpenFin.ConstructorOverride[] = [defaultBroker]; + + if (customSettings?.cloudInteropProvider?.enabled === true) { + console.log("Initializing the cloud interop override"); + const initializedCloudInteropOverride = (await cloudInteropOverride( + customSettings.cloudInteropProvider + )) as unknown as OpenFin.ConstructorOverride; + interopOverride.push(initializedCloudInteropOverride); + } + await init({ browser: { defaultWindowOptions: { @@ -50,7 +63,7 @@ async function initializeWorkspacePlatform(customSettings: CustomSettings): Prom } ], // Use an override for the platform interop to handle the context and intents - interopOverride: (interopBroker) => createInteropOverride(customSettings, interopBroker) + interopOverride }); } diff --git a/how-to/support-context-and-intents/client/src/shapes.ts b/how-to/support-context-and-intents/client/src/shapes.ts index 4f6dbe644e..73e9201bf0 100644 --- a/how-to/support-context-and-intents/client/src/shapes.ts +++ b/how-to/support-context-and-intents/client/src/shapes.ts @@ -1,3 +1,5 @@ +import type { ConnectParams } from "@openfin/cloud-interop/dist/interfaces"; + /** * The custom settings stored in the manifest.fin.json. */ @@ -11,6 +13,11 @@ export interface CustomSettings { * Provider for platform configuration. */ platformProvider?: PlatformProviderSettings; + + /** + * Provider for cloud interop configuration. + */ + cloudInteropProvider?: CloudInteropProviderSettings; } /** @@ -46,3 +53,18 @@ export interface AppProviderSettings { */ cacheDurationInMinutes?: number; } + +/** + * Settings for the cloud interop provider. + */ +export interface CloudInteropProviderSettings extends ConnectParams { + /** + * Is the cloud interop provider enabled + */ + enabled: boolean; + + /** + * The connect parameters for the cloud interop provider. + */ + connectParams: ConnectParams; +} diff --git a/how-to/support-context-and-intents/package.json b/how-to/support-context-and-intents/package.json index a8efa800e8..ba4a934a0c 100644 --- a/how-to/support-context-and-intents/package.json +++ b/how-to/support-context-and-intents/package.json @@ -21,6 +21,7 @@ "author": "john.mandia@openfin.co", "license": "SEE LICENSE IN LICENSE.MD", "dependencies": { + "@openfin/cloud-interop": "^0.4.0", "@openfin/workspace": "18.0.7", "@openfin/workspace-platform": "18.0.7" }, diff --git a/how-to/support-context-and-intents/public/manifest.fin.json b/how-to/support-context-and-intents/public/manifest.fin.json index c6fba48c61..c96c310e23 100644 --- a/how-to/support-context-and-intents/public/manifest.fin.json +++ b/how-to/support-context-and-intents/public/manifest.fin.json @@ -69,6 +69,18 @@ "window", "inline-appasset" ] + }, + "cloudInteropProvider": { + "enabled": false, + "connectParams": { + "url": "", + "userId": "", + "password": "", + "platformId": "", + "sourceId": "", + "sourceDisplayName": "", + "realm": "default" + } } } } diff --git a/how-to/support-context-and-intents/public/second.manifest.fin.json b/how-to/support-context-and-intents/public/second.manifest.fin.json index 61551e431c..da3c2e59ac 100644 --- a/how-to/support-context-and-intents/public/second.manifest.fin.json +++ b/how-to/support-context-and-intents/public/second.manifest.fin.json @@ -54,6 +54,18 @@ ], "cacheDurationInMinutes": 1, "manifestTypes": ["view", "snapshot", "manifest", "external", "inline-view"] + }, + "cloudInteropProvider": { + "enabled": false, + "connectParams": { + "url": "", + "userId": "", + "password": "", + "platformId": "", + "sourceId": "", + "sourceDisplayName": "", + "realm": "default" + } } } } diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index bb21dc875c..fe37735b1b 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,7 @@ ## v18.0.0 +- Added a cloud interop override module so that you can easily test out OpenFin's cloud interop offering. See [How To Add Cloud Interop To Your Interop Broker](./docs/how-to-add-cloud-interop-to-your-interop-broker.md). - Broke up the build process to make it easier to just build your modules. `npm run build` still builds everything and `npm run build-client` still builds all client related code but now if you change framework files you can use `npm run build-framework`, or if you modify our starter modules you can use `npm run build-starter-modules` or if you just want to build your modules (that are listed in webpack.config.js) then you can use `npm run build-client-modules`. This will let you have a much faster build. - npm run launch now launches via the fins link when running on mac instead of the node adapter. - We now capture the window state when saving a page and apply it if a page is being launched into a new window. diff --git a/how-to/workspace-platform-starter/README.md b/how-to/workspace-platform-starter/README.md index f9f32c05a8..bd30963e5c 100644 --- a/how-to/workspace-platform-starter/README.md +++ b/how-to/workspace-platform-starter/README.md @@ -50,6 +50,7 @@ The information below provides information related to configuring and using the | [Configure Your Platform's Intent Support](./docs/how-to-configure-fdc3-intents.md) | How to configure your platform's Intent support. What UI to present to the user if they have to make an application selection after an intent is raised. | | [Add FDC3 Open Support To Your App](./docs/how-to-add-open-support-to-your-app.md) | If you have added one or more apps to your platform you may wish to have them easily opened using fdc3.open with the option of passing context. | | [Customize Your Interop Broker](./docs/how-to-customize-your-interop-broker.md) | You now have control over the interop broker beyond settings. You can use the default implementation, replace it or extend it without having to touch the main codebase. | +| [Add Cloud Interop To Your Interop Broker](./docs/how-to-add-cloud-interop-to-your-interop-broker.md) | OpenFin supports sharing context across platforms and devices using our cloud offering. You can now easily add your cloud interop settings to our cloud interop module and simply enable it to see it in action. | | [Use Notifications](./docs/how-to-use-notifications.md) | Your platform or you app(s) may want to get the end user's attention and capture a response. | | [Customize The Bootstrapping Process](./docs/how-to-customize-the-bootstrapping-process.md) | This section covers how you can manage what gets registered and what background behavior do you want to run (e.g. do you want to register all of the Workspace Components or just some of them?). | | [Theme Your Platform](./docs/how-to-theme-your-platform.md) | The workspace components support a dark theme out of the box. This section covers how to define the theme and logo for your platform and some tools that make that process easier. | diff --git a/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/index.ts b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/index.ts new file mode 100644 index 0000000000..e4bfc45c20 --- /dev/null +++ b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/index.ts @@ -0,0 +1,9 @@ +import type { ModuleImplementation, ModuleTypes } from "workspace-platform-starter/shapes/module-shapes"; +import { OpenFinCloudInterop } from "./interop-override"; + +/** + * Define the entry points for the module. + */ +export const entryPoints: { [type in ModuleTypes]?: ModuleImplementation } = { + interopOverride: new OpenFinCloudInterop() +}; diff --git a/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/interop-override.ts b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/interop-override.ts new file mode 100644 index 0000000000..602bc38c26 --- /dev/null +++ b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/interop-override.ts @@ -0,0 +1,97 @@ +// eslint-disable-next-line max-classes-per-file +import { cloudInteropOverride } from "@openfin/cloud-interop"; +import type OpenFin from "@openfin/core"; +import type { + PlatformInteropOverride, + PlatformInteropOverrideOptions +} from "workspace-platform-starter/shapes/interopbroker-shapes"; +import type { Logger, LoggerCreator } from "workspace-platform-starter/shapes/logger-shapes"; +import type { ModuleDefinition, ModuleHelpers } from "workspace-platform-starter/shapes/module-shapes"; +import { isStringValue } from "workspace-platform-starter/utils"; +import type { OpenFinCloudInteropOptions } from "./shapes"; + +/** + * Implementation for the openfin cloud interop interop override. + */ +export class OpenFinCloudInterop implements PlatformInteropOverride { + /** + * The module definition including settings. + * @internal + */ + private _definition: ModuleDefinition | undefined; + + /** + * The logger for displaying information from the module. + * @internal + */ + private _logger?: Logger; + + /** + * Helper methods for the module. + * @internal + */ + private _helpers: ModuleHelpers | undefined; + + /** + * Initialize the module. + * @param definition The definition of the module from configuration include custom options. + * @param loggerCreator For logging entries. + * @param helpers Helper methods for the module to interact with the application core. + * @returns Nothing. + */ + public async initialize( + definition: ModuleDefinition, + loggerCreator: LoggerCreator, + helpers: ModuleHelpers + ): Promise { + this._definition = definition; + const loggerName = definition.data?.loggerName ?? "OpenfinCloudInterop"; + this._logger = loggerCreator(loggerName); + this._helpers = helpers; + + this._logger.info("Initializing"); + } + + /** + * Close down any resources being used by the module. + * @returns Nothing. + */ + public async closedown(): Promise { + this._logger?.info("Closedown"); + } + + /** + * Get the override constructor for the interop broker (useful if you wish this implementation to be layered with other implementations and passed to the platform's initialization object as part of an array). + * @param options The options for the interop broker defined as part of the platform. + * @returns The override constructor to be used in an array. + */ + public async getConstructorOverride( + options: PlatformInteropOverrideOptions + ): Promise> { + if ( + !isStringValue(this._definition?.data?.userId) || + !isStringValue(this._definition?.data?.password) || + !isStringValue(this._definition?.data?.platformId) || + !isStringValue(this._definition?.data?.url) + ) { + const errorMessage = `The data setting for the interopOverride module ${this._definition?.id} is missing one of the following settings: userId, password, platformId, url.`; + this._logger?.error(errorMessage); + throw new Error(errorMessage); + } + const cloudConfig: OpenFinCloudInteropOptions = { + userId: this._definition?.data?.userId, + password: this._definition?.data?.password, + platformId: this._definition?.data?.platformId, + url: this._definition?.data?.url, + realm: this._definition?.data?.realm, + sourceDisplayName: this._definition.data.sourceDisplayName, + sourceId: isStringValue(this._definition?.data?.sourceId) + ? this._definition?.data?.sourceId + : fin.me.identity.uuid + }; + const initializedCloudInteropOverride = (await cloudInteropOverride( + cloudConfig + )) as unknown as OpenFin.ConstructorOverride; + return initializedCloudInteropOverride; + } +} diff --git a/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/shapes.ts b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/shapes.ts new file mode 100644 index 0000000000..bdbd803d7f --- /dev/null +++ b/how-to/workspace-platform-starter/client/src/modules/interop-override/openfin-cloud-interop/shapes.ts @@ -0,0 +1,10 @@ +import type { ConnectParams } from "@openfin/cloud-interop/dist/interfaces"; +/** + * Options for the openfin cloud interop interop override. These settings can be provided by OpenFin and user credentials should not be checked in. + */ +export interface OpenFinCloudInteropOptions extends ConnectParams { + /** + * Optional name for the logger of this module. + */ + loggerName?: string; +} diff --git a/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js b/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js index a5cbe74ce9..23877c9a1a 100644 --- a/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js +++ b/how-to/workspace-platform-starter/client/starter-modules.webpack.config.js @@ -716,6 +716,28 @@ const configs = [ experiments: { outputModule: true } + }, + { + entry: './client/src/modules/interop-override/openfin-cloud-interop/index.ts', + devtool: 'source-map', + module: { + rules: [loaderRule] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + alias + }, + externals: { fin: 'fin' }, + output: { + filename: 'openfin-cloud-interop.bundle.js', + library: { + type: 'module' + }, + path: path.resolve(__dirname, '..', 'public', 'js', 'modules', 'interop-override') + }, + experiments: { + outputModule: true + } } ]; diff --git a/how-to/workspace-platform-starter/docs/how-to-add-cloud-interop-to-your-interop-broker.md b/how-to/workspace-platform-starter/docs/how-to-add-cloud-interop-to-your-interop-broker.md new file mode 100644 index 0000000000..f535e1aa6b --- /dev/null +++ b/how-to/workspace-platform-starter/docs/how-to-add-cloud-interop-to-your-interop-broker.md @@ -0,0 +1,61 @@ +> **_:information_source: OpenFin Workspace:_** [OpenFin Workspace](https://www.openfin.co/workspace/) is a commercial product and this repo is for evaluation purposes (See [LICENSE.MD](../LICENSE.MD)). Use of the OpenFin Container and OpenFin Workspace components is only granted pursuant to a license from OpenFin (see [manifest](../public/manifest.fin.json)). Please [**contact us**](https://www.openfin.co/workspace/poc/) if you would like to request a developer evaluation key or to discuss a production license. + +[<- Back to Table Of Contents](../README.md) + +# How To Add Cloud Interop To Your Interop Broker + +Workspace Platform Starter includes a default interop broker override that includes support for FDC3 2.0 and intents as well as context. It has been built to support interop with support for the Platform Apps format used by Workspace Platform Starter (directories can still use the FDC3 1.2 & 2.0 format as these are mapped internally to the PlatformApp format). + +OpenFin Workspace 18.0+ lets you specify an array of interop overrides that can be layered on top of each other so that different overrides can add custom behavior. + +Workspace Platform Starter 18.0 supports this ability by adding module support to platformProvider.interop and this support lets us easily offer optional cloud interop support through a module. + +## Cloud Interop interop override is available as a module + +Our default interop broker is now available as a module and you can easily generate your own interop broker override: See [How To Customize Your Interop Broker](./how-to-customize-your-interop-broker.md). + +To make it easy to test OpenFin's cloud interop support we have generated an [openfin-cloud-interop](../client/src/modules/interop-override/openfin-cloud-interop/interop-override.ts) that imports and configures the [@openfin/cloud-interop](https://www.npmjs.com/package/@openfin/cloud-interop) npm module. + +You can see this in platformProvider.interop section of the [manifest.fin.json](../public/manifest.fin.json) and [settings.json](../public/settings.json) files (an example is shown below). + +### Settings + +The settings are in a manifest and static settings.json file but this type of information is best served from a service after the user has authenticated. Do not check in your credentials. Please contact your OpenFin Sales Account Manager to get your cloud credentials. + +```json +"platformProvider": { + ... + "interop": { + "modules": [ + { + "id": "openfin-cloud-interop", + "icon": "http://localhost:8080/favicon.ico", + "title": "OpenFin Cloud Interop", + "description": "OpenFin Cloud Interop", + "enabled": false, + "url": "http://localhost:8080/js/modules/interop-override/openfin-cloud-interop.bundle.js", + "data": { + "userId": "", + "password": "", + "platformId": "", + "url": "", + "sourceDisplayName":"", + "sourceId": "" + } + } + ] + } +} +``` + +Once you have cloud interop enabled you will be able to share context across user channels (green, yellow, red etc) across devices and platforms. + +## Other Examples + +We have also updated our _support-context-and-intents_ how-to example to optionally support cloud interop. This is a much simpler example and doesn't use the module pattern which is useful if you have your own workspace platform and you just want to see how to use the [@openfin/cloud-interop](https://www.npmjs.com/package/@openfin/cloud-interop) npm module. + +## Source Reference + +- [OpenFin Cloud Interop Override Module](../client/src/modules/interop-override/openfin-cloud-interop/) + +[<- Back to Table Of Contents](../README.md) diff --git a/how-to/workspace-platform-starter/docs/how-to-customize-your-interop-broker.md b/how-to/workspace-platform-starter/docs/how-to-customize-your-interop-broker.md index 4c428bd9e4..9b6bebe5fc 100644 --- a/how-to/workspace-platform-starter/docs/how-to-customize-your-interop-broker.md +++ b/how-to/workspace-platform-starter/docs/how-to-customize-your-interop-broker.md @@ -4,11 +4,11 @@ # How To Customize Your Interop Broker -Workspace Platform Starter includes a default interop broker override that includes support for FDC3 2.0 and intents as well as context. If has been built to support interop with support for the Platform Apps format used by Workspace Platform Starter (directories can still use the FDC3 1.2 & 2.0 format as these are mapped internally to the PlatformApp format). +Workspace Platform Starter includes a default interop broker override that includes support for FDC3 2.0 and intents as well as context. It has been built to support interop with support for the Platform Apps format used by Workspace Platform Starter (directories can still use the FDC3 1.2 & 2.0 format as these are mapped internally to the PlatformApp format). -OpenFin Workspace 17.4+ lets you specify an array of interop overrides that can be layered on top of each other so that different overrides can add custom behavior. +OpenFin Workspace 18.0+ lets you specify an array of interop overrides that can be layered on top of each other so that different overrides can add custom behavior. -Workspace Platform Starter 17.4 supports this ability by adding module support to platformProvider.interop. +Workspace Platform Starter 18.0 supports this ability by adding module support to platformProvider.interop. ## default workspace platform interop override is now a module @@ -22,7 +22,7 @@ If you do not include our default implementation in the modules array then you w ## modules -The ability to specify an [array of interop override constructors](https://cdn.openfin.co/docs/javascript/stable/interfaces/OpenFin.InitPlatformOptions.html#interopOverride) was introduced in the v33 release of the OpenFin runtime and is now exposed to your workspace platform in version 17.4 of workspace. +The ability to specify an [array of interop override constructors](https://cdn.openfin.co/docs/javascript/stable/interfaces/OpenFin.InitPlatformOptions.html#interopOverride) was introduced in the v33 release of the OpenFin runtime and is now exposed to your workspace platform in version 18.0 of workspace. These are interop modules that provide custom interop broker logic. If there are more than one then they will extend each other (the earlier entries will act as the base for subsequent entries). If you wish to use the Workspace Platform Starter interop override module as a base for your interop overrides so it should be at the start of the modules array. Here is an extract from [manifest.fin.json](../public/manifest.fin.json): diff --git a/how-to/workspace-platform-starter/package.json b/how-to/workspace-platform-starter/package.json index d1bb08df6b..dc15d94e8b 100644 --- a/how-to/workspace-platform-starter/package.json +++ b/how-to/workspace-platform-starter/package.json @@ -59,6 +59,7 @@ "license": "SEE LICENSE IN LICENSE.MD", "dependencies": { "@finos/fdc3": "^2.0.3", + "@openfin/cloud-interop": "^0.4.0", "@openfin/openid-connect": "^1.0.0", "@openfin/snap-sdk": "0.2.0", "@openfin/workspace": "18.0.7", diff --git a/how-to/workspace-platform-starter/public/manifest.fin.json b/how-to/workspace-platform-starter/public/manifest.fin.json index 2f368d3694..7ef93e85d8 100644 --- a/how-to/workspace-platform-starter/public/manifest.fin.json +++ b/how-to/workspace-platform-starter/public/manifest.fin.json @@ -176,6 +176,22 @@ "data": { "loggerName": "WpsInteropOverride" } + }, + { + "id": "openfin-cloud-interop", + "icon": "http://localhost:8080/favicon.ico", + "title": "OpenFin Cloud Interop", + "description": "OpenFin Cloud Interop", + "enabled": false, + "url": "http://localhost:8080/js/modules/interop-override/openfin-cloud-interop.bundle.js", + "data": { + "userId": "", + "password": "", + "platformId": "", + "url": "", + "sourceDisplayName": "", + "sourceId": "" + } } ] } diff --git a/how-to/workspace-platform-starter/public/settings.json b/how-to/workspace-platform-starter/public/settings.json index 1453f8181b..954b8700a6 100644 --- a/how-to/workspace-platform-starter/public/settings.json +++ b/how-to/workspace-platform-starter/public/settings.json @@ -106,6 +106,22 @@ "data": { "loggerName": "WpsInteropOverride" } + }, + { + "id": "openfin-cloud-interop", + "icon": "http://localhost:8080/favicon.ico", + "title": "OpenFin Cloud Interop", + "description": "OpenFin Cloud Interop", + "enabled": false, + "url": "http://localhost:8080/js/modules/interop-override/openfin-cloud-interop.bundle.js", + "data": { + "userId": "", + "password": "", + "platformId": "", + "url": "", + "sourceDisplayName": "", + "sourceId": "" + } } ] } diff --git a/package-lock.json b/package-lock.json index d8fbd5a6bf..38214f0f14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -955,6 +955,7 @@ "version": "18.0.0", "license": "SEE LICENSE IN LICENSE.MD", "dependencies": { + "@openfin/cloud-interop": "^0.4.0", "@openfin/workspace": "18.0.7", "@openfin/workspace-platform": "18.0.7" }, @@ -1108,6 +1109,7 @@ "license": "SEE LICENSE IN LICENSE.MD", "dependencies": { "@finos/fdc3": "^2.0.3", + "@openfin/cloud-interop": "^0.4.0", "@openfin/openid-connect": "^1.0.0", "@openfin/snap-sdk": "0.2.0", "@openfin/workspace": "18.0.7", @@ -3641,6 +3643,51 @@ "resolved": "https://registry.npmjs.org/@finos/fdc3/-/fdc3-2.1.0-beta.7.tgz", "integrity": "sha512-YtNKYPk2daq4ByS7WccRiYxTi80/GXTPObYmbNiS9OXA4+Er/JwCB77CkVCL+TQ8z/LWzPulR+w4PParLTXdKA==" }, + "node_modules/@openfin/cloud-interop": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@openfin/cloud-interop/-/cloud-interop-0.4.0.tgz", + "integrity": "sha512-rXifPr8RjJC8SO/YXp0RnWaXJdEbRyYXg1LEnmsNaPp1cL6r088LKBrkMTKYkRDZj9Z9CDieWxbbKpeAJ6+fBg==", + "dependencies": { + "@openfin/core": "^37.80.39", + "axios": "^1.6.2", + "mqtt": "^5.3.1" + } + }, + "node_modules/@openfin/cloud-interop/node_modules/@openfin/core": { + "version": "37.81.17", + "resolved": "https://registry.npmjs.org/@openfin/core/-/core-37.81.17.tgz", + "integrity": "sha512-EFpXM/420GPPgFoOs5Fh9GRo5by1wOt35DKC3Rd12pZwCNeZTHpkgDHljQK/sTfbGzJqvZ/DpIJjKJRkwHMmig==", + "dependencies": { + "@types/node": "^16.0.0", + "lodash": "^4.17.21", + "ws": "^7.3.0" + } + }, + "node_modules/@openfin/cloud-interop/node_modules/@types/node": { + "version": "16.18.96", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.96.tgz", + "integrity": "sha512-84iSqGXoO+Ha16j8pRZ/L90vDMKX04QTYMTfYeE1WrjWaZXuchBehGUZEpNgx7JnmlrIHdnABmpjrQjhCnNldQ==" + }, + "node_modules/@openfin/cloud-interop/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@openfin/core": { "version": "36.80.8", "resolved": "https://registry.npmjs.org/@openfin/core/-/core-36.80.8.tgz", @@ -5085,6 +5132,20 @@ "redux": "^4.0.0" } }, + "node_modules/@types/readable-stream": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.11.tgz", + "integrity": "sha512-R3eUMUTTKoIoaz7UpYLxvZCrOmCRPRbAmoDDHKcimTEySltaJhF8hLzj4+EzyDifiX5eK6oDQGSfmNnXjxZzYQ==", + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -5141,7 +5202,6 @@ "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -7909,8 +7969,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/automation-testing-register-with-home": { "resolved": "how-to/automation-testing/register-with-home-ts", @@ -7989,7 +8048,6 @@ "version": "1.6.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dev": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -9102,7 +9160,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9128,6 +9185,11 @@ "node": ">= 12.0.0" } }, + "node_modules/commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" + }, "node_modules/compare-versions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", @@ -9236,6 +9298,33 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", @@ -10016,7 +10105,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -11609,6 +11697,18 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "dependencies": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.1.0" + } + }, "node_modules/fast-xml-parser": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz", @@ -12196,7 +12296,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -12252,7 +12351,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -13041,6 +13139,11 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "node_modules/hey-listen": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", @@ -15006,6 +15109,15 @@ "dev": true, "peer": true }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -16054,7 +16166,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16254,6 +16365,197 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/mqtt": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.5.2.tgz", + "integrity": "sha512-dlKxINBrrorgMp1A5UHQVf5GAkn1m/dY12W2Sp6LAY794RxQ0OPo0Q9N2S3qrNRjjC1WETA/9oYR6yadhR3siw==", + "dependencies": { + "@types/readable-stream": "^4.0.5", + "@types/ws": "^8.5.9", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.3.4", + "help-me": "^5.0.0", + "lru-cache": "^10.0.1", + "minimist": "^1.2.8", + "mqtt": "^5.2.0", + "mqtt-packet": "^9.0.0", + "number-allocator": "^1.0.14", + "readable-stream": "^4.4.2", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^4.2.0", + "worker-timers": "^7.1.4", + "ws": "^8.14.2" + }, + "bin": { + "mqtt": "build/bin/mqtt.js", + "mqtt_pub": "build/bin/pub.js", + "mqtt_sub": "build/bin/sub.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz", + "integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt-packet/node_modules/bl": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.12.tgz", + "integrity": "sha512-EnEYHilP93oaOa2MnmNEjAcovPS3JlQZOyzGXi3EyEpPhm9qWvdDp7BmAVEVusGzp8LlwQK56Av+OkDoRjzE0w==", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/mqtt-packet/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/mqtt-packet/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/mqtt-packet/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/mqtt-packet/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/mqtt/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/mqtt/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/mqtt/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/mqtt/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -16541,6 +16843,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, "node_modules/nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", @@ -17697,8 +18008,7 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/progress": { "version": "2.0.3", @@ -17814,8 +18124,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/ps-list": { "version": "7.2.0", @@ -18774,6 +19083,11 @@ "jsesc": "bin/jsesc" } }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, "node_modules/remove-accents": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", @@ -18959,6 +19273,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, "node_modules/rgb2hex": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", @@ -19599,7 +19918,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, "engines": { "node": ">= 10.x" } @@ -19666,7 +19984,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -19674,8 +19991,7 @@ "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/string-length": { "version": "4.0.2", @@ -20872,6 +21188,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -21151,8 +21472,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -21760,6 +22080,37 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "node_modules/worker-timers": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.7.tgz", + "integrity": "sha512-Dr4La61d94SjOA8P57h2LN8W3MXOVe/m1P7jER8cmuIy+JaDMqPttSwo6QRJFSK6YnG9cD6SU7J8m7CVlu8jlw==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.7", + "worker-timers-worker": "^7.0.70" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.7.tgz", + "integrity": "sha512-8hb4lSMAijDY/Dp/MOw9Hc2x6uU59XWFYjcWQgC4bai+sxcLXjeexd9aYKdYMFZPiPoieGzMYIs9WGpv2Co3eA==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.70" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.70", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.70.tgz", + "integrity": "sha512-lemWEME0RHB78hzGkkQcKfF6L82gqVhV3T9iY14jHBhbLxLq9t1RRCLmPDBZV7sdnUoW6Khkfn6coqPjgEK6cw==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "tslib": "^2.6.2" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -21823,7 +22174,6 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, "engines": { "node": ">=10.0.0" }, From bf7ffcf8ccb4284d318e765cc24a86c94293460b Mon Sep 17 00:00:00 2001 From: John Date: Tue, 16 Apr 2024 21:23:31 +0100 Subject: [PATCH 10/10] Added option of creating analytics for your modules (except analytics modules) --- .../workspace-platform-starter/CHANGELOG.md | 1 + .../client/src/framework/analytics.ts | 10 ++++++- .../client/src/framework/modules.ts | 25 +++++++++++++++++ .../src/framework/shapes/analytics-shapes.ts | 25 ++++++++++++++++- .../src/framework/shapes/module-shapes.ts | 7 +++++ .../types/module/shapes/analytics-shapes.d.ts | 22 ++++++++++++++- .../types/module/shapes/module-shapes.d.ts | 6 ++++ .../docs/how-to-add-a-module.md | 6 +++- .../docs/how-to-configure-analytics.md | 28 +++++++++++++++++++ 9 files changed, 126 insertions(+), 4 deletions(-) diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index fe37735b1b..9004ab816f 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,7 @@ ## v18.0.0 +- Module Helpers now provide a getAnalyticsClient (it is marked as optional and the result could be undefined so it leaves the option for it to be denied to a module or removed). This client supports a ModuleAnalytic event which will have a source of Module assigned to it (you can still specify type and use the data property to provide additional module specific information). This data will be passed to the analyticProviders that receive the Workspace Analytic events. See [How to Configure Analytics](./docs/how-to-configure-analytics.md). - Added a cloud interop override module so that you can easily test out OpenFin's cloud interop offering. See [How To Add Cloud Interop To Your Interop Broker](./docs/how-to-add-cloud-interop-to-your-interop-broker.md). - Broke up the build process to make it easier to just build your modules. `npm run build` still builds everything and `npm run build-client` still builds all client related code but now if you change framework files you can use `npm run build-framework`, or if you modify our starter modules you can use `npm run build-starter-modules` or if you just want to build your modules (that are listed in webpack.config.js) then you can use `npm run build-client-modules`. This will let you have a much faster build. - npm run launch now launches via the fins link when running on mac instead of the node adapter. diff --git a/how-to/workspace-platform-starter/client/src/framework/analytics.ts b/how-to/workspace-platform-starter/client/src/framework/analytics.ts index 0a279dfb0a..99510d08d2 100644 --- a/how-to/workspace-platform-starter/client/src/framework/analytics.ts +++ b/how-to/workspace-platform-starter/client/src/framework/analytics.ts @@ -23,7 +23,15 @@ export async function init( if (options) { logger.info("Initializing with options", options); modules = await loadModules(options, "analytics"); - await initializeModules(modules, helpers); + // eslint-disable-next-line @typescript-eslint/unbound-method + const { getAnalyticsClient, ...analyticsHelper } = helpers; + + if (getAnalyticsClient) { + logger.info( + "getAnalyticsClient is defined as part of helpers but not passed to analytics modules. This is to prevent an endless loop where an analytics module may be feeding events to itself." + ); + } + await initializeModules(modules, analyticsHelper); isAnalyticsEnabled = modules.length > 0; } } diff --git a/how-to/workspace-platform-starter/client/src/framework/modules.ts b/how-to/workspace-platform-starter/client/src/framework/modules.ts index ba698be277..5dee932dcf 100644 --- a/how-to/workspace-platform-starter/client/src/framework/modules.ts +++ b/how-to/workspace-platform-starter/client/src/framework/modules.ts @@ -4,6 +4,7 @@ import { type BrowserWindowModule, type WorkspacePlatformModule } from "@openfin/workspace-platform"; +import { handleAnalytics } from "./analytics"; import { getApp, getApps } from "./apps"; import { checkCondition, conditionChanged } from "./conditions"; import * as connectionProvider from "./connections"; @@ -17,6 +18,12 @@ import { createLogger } from "./logger-provider"; import { MANIFEST_TYPES } from "./manifest-types"; import * as Menu from "./menu"; import { launchPage, launchView } from "./platform/browser"; +import { + MODULE_ANALYTICS_SOURCE, + type AnalyticsClient, + type ModuleAnalyticsEvent, + type PlatformAnalyticsEvent +} from "./shapes/analytics-shapes"; import type { PlatformApp, PlatformAppIdentifier, UpdatableLaunchPreference } from "./shapes/app-shapes"; import type { ConditionContextTypes, ConditionsClient } from "./shapes/conditions-shapes"; import type { ConnectionValidationOptions, ConnectionValidationResponse } from "./shapes/connection-shapes"; @@ -283,6 +290,7 @@ export function getDefaultHelpers(): ModuleHelpers { sessionId: passedSessionId, bringAppToFront: bringToFront, getPlatform: getCurrentSync, + getAnalyticsClient, getApps: async (): Promise => { logger.info("getApps: getting public apps for module."); return getApps({ private: false }); @@ -445,6 +453,23 @@ async function getMenuClient(): Promise { }; } +/** + * Get analytics client. + * @returns The analytics client. + */ +async function getAnalyticsClient(): Promise { + return { + handleAnalytics: async (events: ModuleAnalyticsEvent[]): Promise => { + if (Array.isArray(events)) { + const platformAnalyticEvents: PlatformAnalyticsEvent[] = events.map( + (entry) => ({ ...entry, source: MODULE_ANALYTICS_SOURCE }) + ); + return handleAnalytics(platformAnalyticEvents); + } + } + }; +} + /** * Get the conditions client to use with the modules. * @returns The conditions client. diff --git a/how-to/workspace-platform-starter/client/src/framework/shapes/analytics-shapes.ts b/how-to/workspace-platform-starter/client/src/framework/shapes/analytics-shapes.ts index 565c383bd8..ca1617e705 100644 --- a/how-to/workspace-platform-starter/client/src/framework/shapes/analytics-shapes.ts +++ b/how-to/workspace-platform-starter/client/src/framework/shapes/analytics-shapes.ts @@ -30,6 +30,11 @@ export interface AnalyticsProviderOptions extends ModuleList { */ export const PLATFORM_ANALYTICS_SOURCE = "WorkspacePlatform"; +/** + * Additional source for module events. + */ +export const MODULE_ANALYTICS_SOURCE = "Module"; + /** * The data for the analytics events that need to be handled. Extends the platform AnalyticsEvent with additional data * source. @@ -38,10 +43,28 @@ export interface PlatformAnalyticsEvent extends Omit { /** * The source of the event. */ - source: typeof PLATFORM_ANALYTICS_SOURCE | AnalyticsSource; + source: typeof PLATFORM_ANALYTICS_SOURCE | typeof MODULE_ANALYTICS_SOURCE | AnalyticsSource; /** * The timestamp for the event. */ timestamp: Date; } + +/** + * The data for the analytics events that need to be handled. Extends the platform AnalyticsEvent but enforces source as + * Module. Modules can use type (to specify module id) and use action, value and data to provide module specific information if required. + */ +export type ModuleAnalyticsEvent = Omit; + +/** + * Provides a client for handling analytics events. + */ +export interface AnalyticsClient { + /** + * Handle a list of analytics events. + * @param events The events to handle. + * @returns Nothing. + */ + handleAnalytics(events: ModuleAnalyticsEvent[]): Promise; +} diff --git a/how-to/workspace-platform-starter/client/src/framework/shapes/module-shapes.ts b/how-to/workspace-platform-starter/client/src/framework/shapes/module-shapes.ts index 0b42fd93ee..294bb045a7 100644 --- a/how-to/workspace-platform-starter/client/src/framework/shapes/module-shapes.ts +++ b/how-to/workspace-platform-starter/client/src/framework/shapes/module-shapes.ts @@ -1,5 +1,6 @@ import type OpenFin from "@openfin/core"; import type { BrowserWindowModule, WorkspacePlatformModule } from "@openfin/workspace-platform"; +import type { AnalyticsClient } from "./analytics-shapes"; import type { PlatformApp, PlatformAppIdentifier, UpdatableLaunchPreference } from "./app-shapes"; import type { ConditionsClient } from "./conditions-shapes"; import type { ConnectionValidationOptions, ConnectionValidationResponse } from "./connection-shapes"; @@ -93,6 +94,12 @@ export interface ModuleHelpers { */ getPlatform?(): WorkspacePlatformModule; + /** + * Get Analytics Client. + * @returns The analytics client that can be used to feed analytics to the analytics provider or undefined if it isn't available. + */ + getAnalyticsClient?(): Promise; + /** * Get the list of apps supported by this platform and/or user. * @returns The list of platform apps available from the module. diff --git a/how-to/workspace-platform-starter/client/types/module/shapes/analytics-shapes.d.ts b/how-to/workspace-platform-starter/client/types/module/shapes/analytics-shapes.d.ts index fd0aaabcd4..cfda19adb9 100644 --- a/how-to/workspace-platform-starter/client/types/module/shapes/analytics-shapes.d.ts +++ b/how-to/workspace-platform-starter/client/types/module/shapes/analytics-shapes.d.ts @@ -26,6 +26,10 @@ export interface AnalyticsProviderOptions extends ModuleList { * Additional source for workspace platform events. */ export declare const PLATFORM_ANALYTICS_SOURCE = "WorkspacePlatform"; +/** + * Additional source for module events. + */ +export declare const MODULE_ANALYTICS_SOURCE = "Module"; /** * The data for the analytics events that need to be handled. Extends the platform AnalyticsEvent with additional data * source. @@ -34,9 +38,25 @@ export interface PlatformAnalyticsEvent extends Omit { /** * The source of the event. */ - source: typeof PLATFORM_ANALYTICS_SOURCE | AnalyticsSource; + source: typeof PLATFORM_ANALYTICS_SOURCE | typeof MODULE_ANALYTICS_SOURCE | AnalyticsSource; /** * The timestamp for the event. */ timestamp: Date; } +/** + * The data for the analytics events that need to be handled. Extends the platform AnalyticsEvent but enforces source as + * Module. Modules can use type (to specify module id) and use action, value and data to provide module specific information if required. + */ +export type ModuleAnalyticsEvent = Omit; +/** + * Provides a client for handling analytics events. + */ +export interface AnalyticsClient { + /** + * Handle a list of analytics events. + * @param events The events to handle. + * @returns Nothing. + */ + handleAnalytics(events: ModuleAnalyticsEvent[]): Promise; +} diff --git a/how-to/workspace-platform-starter/client/types/module/shapes/module-shapes.d.ts b/how-to/workspace-platform-starter/client/types/module/shapes/module-shapes.d.ts index b003930444..0c4a7abc61 100644 --- a/how-to/workspace-platform-starter/client/types/module/shapes/module-shapes.d.ts +++ b/how-to/workspace-platform-starter/client/types/module/shapes/module-shapes.d.ts @@ -1,5 +1,6 @@ import type OpenFin from "@openfin/core"; import type { BrowserWindowModule, WorkspacePlatformModule } from "@openfin/workspace-platform"; +import type { AnalyticsClient } from "./analytics-shapes"; import type { PlatformApp, PlatformAppIdentifier, UpdatableLaunchPreference } from "./app-shapes"; import type { ConditionsClient } from "./conditions-shapes"; import type { ConnectionValidationOptions, ConnectionValidationResponse } from "./connection-shapes"; @@ -80,6 +81,11 @@ export interface ModuleHelpers { * @returns The current platform. */ getPlatform?(): WorkspacePlatformModule; + /** + * Get Analytics Client. + * @returns The analytics client that can be used to feed analytics to the analytics provider or undefined if it isn't available. + */ + getAnalyticsClient?(): Promise; /** * Get the list of apps supported by this platform and/or user. * @returns The list of platform apps available from the module. diff --git a/how-to/workspace-platform-starter/docs/how-to-add-a-module.md b/how-to/workspace-platform-starter/docs/how-to-add-a-module.md index f5a98d2915..4aa0bcc958 100644 --- a/how-to/workspace-platform-starter/docs/how-to-add-a-module.md +++ b/how-to/workspace-platform-starter/docs/how-to-add-a-module.md @@ -12,11 +12,15 @@ The following features are currently extendable using modules: - analytics - auth - conditions +- content-creation - endpoint -- initOptions +- init-options - integrations +- interop-override - lifecycle - log +- menus +- share ## Configuration diff --git a/how-to/workspace-platform-starter/docs/how-to-configure-analytics.md b/how-to/workspace-platform-starter/docs/how-to-configure-analytics.md index 9b50e71709..6d1f2b1265 100644 --- a/how-to/workspace-platform-starter/docs/how-to-configure-analytics.md +++ b/how-to/workspace-platform-starter/docs/how-to-configure-analytics.md @@ -35,6 +35,34 @@ public async handleAnalytics(events: AnalyticsEvent[]) { } ``` +## Module Helper - getAnalyticsClient + +The module helper that gets passed to modules has an optional getAnalyticsClient function that might be available to your module. If available you can use it to request an analytics client. This may come back undefined if there is a reason why it cannot be provided to that module. If available it will let you pass one or more ModuleAnalyticEvents. These events do not have a source setting as this is set to Module but you can specify type and there is a data setting where you can put event/module specific information. This will be passed to the analytics modules so that they can take that feed and do something with it (send to a backend, display on as a report etc). + +> **INFO:** This helper method is not passed to an analytics module to prevent accidental endless loops where submitting an analytical event would go back to the module that submitted it. + +```javascript + if(helpers?.getAnalyticsClient !== undefined) { + const analyticsClient = await helpers.getAnalyticsClient(); + ... + if(analyticsClient !== undefined) { + analyticsClient.handleAnalytics([ + { + action: "Event Happened", + timestamp: new Date(), + type: this._definition?.id ?? "my module", + value: "Custom Value", + data: { } + } + ]); + } + } +``` + +### Existing analytics + +If you are creating an action for the Browser or a Home result through an integration then please remember that since they are being actioned by Workspace Components (Browser/Home) they will already be generating analytical events so you might not need to make use of this helper client. + ## Generate From Template You can generate the scaffold for a new module by using the following command line, where "My Analytics" is the name you want to give your module: