diff --git a/how-to/workspace-platform-starter/CHANGELOG.md b/how-to/workspace-platform-starter/CHANGELOG.md index d86ca8bc3f..a8c54deee3 100644 --- a/how-to/workspace-platform-starter/CHANGELOG.md +++ b/how-to/workspace-platform-starter/CHANGELOG.md @@ -2,6 +2,7 @@ ## v16 +- Improved launchPreference so that now args for a native app (app asset or external) can be specified via launchPreference. Launch preference can also be configured to allow args to be specified dynamically when the launch request is made. Please see [how to define app launch preference](./docs/how-to-define-app-launch-preference.md). - Improved launchPreference so additional options such as url, interop, customData can be specified. Modules can now pass a launchPreference when launching an app by appId. They can see if the app supports being updated by getting the app by id and checking for the updatable setting under launchPreference.options. Only inline-view/view and inline-window/window support updatable launch preferences. Please see [how to define app launch preference](./docs/how-to-define-app-launch-preference.md). - Added support for Snap, enable by setting `customSettings.snapProvider.enabled` to true. Configure the `customSettings.snapProvider.serverAssetInfo` to point to the `SNAP_ASSET_URL`. Enable the Snap debugging window by setting `customSettings.snapProvider.showDebugWindow` to true. - Added new module type `content-creation`, these modules can be used to define content creation rules and handle the associated events. Modules are added in `customSettings.contentCreationProvider` section in manifest. diff --git a/how-to/workspace-platform-starter/client/src/framework/launch.ts b/how-to/workspace-platform-starter/client/src/framework/launch.ts index 0b266a0db6..7bcbbb6e0f 100644 --- a/how-to/workspace-platform-starter/client/src/framework/launch.ts +++ b/how-to/workspace-platform-starter/client/src/framework/launch.ts @@ -54,7 +54,7 @@ export async function launch( switch (app.manifestType) { case MANIFEST_TYPES.External.id: case MANIFEST_TYPES.InlineExternal.id: { - const platformIdentity = await launchExternal(app); + const platformIdentity = await launchExternal(app, undefined, launchPreference); if (platformIdentity) { platformAppIdentities.push(platformIdentity); } @@ -62,7 +62,7 @@ export async function launch( } case MANIFEST_TYPES.Appasset.id: case MANIFEST_TYPES.InlineAppAsset.id: { - const platformIdentity = await launchAppAsset(app); + const platformIdentity = await launchAppAsset(app, undefined, launchPreference); if (platformIdentity) { platformAppIdentities.push(platformIdentity); } @@ -846,11 +846,13 @@ async function launchSnapshot(snapshotApp: PlatformApp): Promise { const options: OpenFin.ExternalProcessRequestType = {}; logger.info(`Request to launch app asset app of type ${appAssetApp.manifestType}`); @@ -881,7 +883,7 @@ export async function launchAppAsset( } try { logger.info(`Launching app asset with appId: ${appAssetApp.appId} with the following options:`, options); - const identity = await launchExternalProcess(appAssetApp, options, instanceId); + const identity = await launchExternalProcess(appAssetApp, options, instanceId, launchPreference); logger.info( `External app with appId: ${appAssetApp.appId} launched with the following identity`, identity @@ -896,11 +898,13 @@ export async function launchAppAsset( * Launch an external for the platform app. * @param externalApp The app to launch external view for. * @param instanceId Provide an instance id for the app being launched. + * @param launchPreference Optional custom launch preferences * @returns The identities of the app parts launched. */ export async function launchExternal( externalApp: PlatformApp, - instanceId?: string + instanceId?: string, + launchPreference?: UpdatableLaunchPreference ): Promise { let options: OpenFin.ExternalProcessRequestType = {}; logger.info(`Request to external app of type ${externalApp.manifestType}`); @@ -922,7 +926,7 @@ export async function launchExternal( `Launching external app asset with appId: ${externalApp.appId} with the following options:`, options ); - const identity = await launchExternalProcess(externalApp, options, instanceId); + const identity = await launchExternalProcess(externalApp, options, instanceId, launchPreference); logger.info( `External app with appId: ${externalApp.appId} launched with the following identity`, identity @@ -938,18 +942,47 @@ export async function launchExternal( * @param app The app being launched. * @param options The launch options. * @param instanceId Provide an instance id for the app being launched. + * @param launchPreference Optional custom launch preferences * @returns The identity of the process. */ async function launchExternalProcess( app: PlatformApp, options: OpenFin.ExternalProcessRequestType, - instanceId?: string + instanceId?: string, + launchPreference?: UpdatableLaunchPreference ): Promise { const nativeOptions = app.launchPreference?.options as NativeLaunchOptions; const hasPath = isStringValue(options.path); let identity: PlatformAppIdentifier | undefined; + + let args: string[] | undefined; + + if (nativeOptions?.type === "native") { + if ( + launchPreference?.options?.type === "native" && + Array.isArray(nativeOptions?.updatable) && + nativeOptions.updatable.length > 0 + ) { + for (const option of nativeOptions.updatable) { + if (option.name === "arguments" && Array.isArray(launchPreference.options.native?.arguments)) { + args = launchPreference.options.native?.arguments; + logger.debug(`Using passed launch preference for the args for app ${app.appId}`, args); + } + } + } + if (isEmpty(args) && Array.isArray(nativeOptions?.native?.arguments)) { + args = nativeOptions.native?.arguments; + logger.debug(`Using app definition based args for app ${app.appId}`, args); + } + } + if (isEmpty(args) && isStringValue(options.arguments)) { + args = [options.arguments]; + } else if (isEmpty(args)) { + args = []; + } + if ( snapProvider.isEnabled() && nativeOptions?.type === "native" && @@ -973,11 +1006,6 @@ async function launchExternalProcess( instanceId = app.instanceMode === "single" ? app.appId : randomUUID(); } - let args = nativeOptions.snap?.args; - if (!isStringValue(args) && isStringValue(options.arguments)) { - args = [options.arguments]; - } - const launchIdentity = await snapProvider.launchApp( path, args, @@ -1001,7 +1029,9 @@ async function launchExternalProcess( } if (isEmpty(identity)) { - const launchIdentity = await fin.System.launchExternalProcess(options); + const clonedOptions = objectClone(options); + clonedOptions.arguments = args.join(" "); + const launchIdentity = await fin.System.launchExternalProcess(clonedOptions); identity = { ...launchIdentity, appId: app.appId }; } diff --git a/how-to/workspace-platform-starter/client/src/framework/shapes/app-shapes.ts b/how-to/workspace-platform-starter/client/src/framework/shapes/app-shapes.ts index 9c292dff76..290276725e 100644 --- a/how-to/workspace-platform-starter/client/src/framework/shapes/app-shapes.ts +++ b/how-to/workspace-platform-starter/client/src/framework/shapes/app-shapes.ts @@ -163,7 +163,7 @@ export interface Preference { /** * What setting is updatable? */ - name: ViewPreferenceName | WebPreferenceName; + name: ViewPreferenceName | WebPreferenceName | NativePreferenceName; /** * Is there a constraint that the platform can apply? @@ -171,6 +171,16 @@ export interface Preference { constraint?: T; } +/** + * Which Launch Options are updatable and are there any constraints + */ +export interface NativePreference extends Preference { + /** + * What setting is updatable? + */ + name: NativePreferenceName; +} + /** * Which Launch Options are updatable and are there any constraints */ @@ -191,6 +201,11 @@ export interface ViewPreferenceUrl extends ViewPreference { /** * What setting is updatable? */ - name: ViewPreferenceName | WebPreferenceName; + name: ViewPreferenceName | WebPreferenceName | NativePreferenceName; /** * Is there a constraint that the platform can apply? */ constraint?: T; } +/** + * Which Launch Options are updatable and are there any constraints + */ +export interface NativePreference extends Preference { + /** + * What setting is updatable? + */ + name: NativePreferenceName; +} /** * Which Launch Options are updatable and are there any constraints */ @@ -169,6 +178,10 @@ export interface ViewPreferenceUrl extends ViewPreference extends Preference { + /** + * What setting is updatable? + */ + name: NativePreferenceName; +} + +/** + * A list of native related settings that can be updated. + */ +export type NativePreferenceName = "arguments"; +``` + +You can see that you can have an updatable array with an object that specify that you want arguments to be dynamically updatable. Without that setting you can still override the arguments but only through the launchPreference within the app definition. + ## Using Launch Preferences from a module When building a module it may have permission to get and launch applications. These helper functions are passed in a helper object when the module is initialized. See [How to add a module](./how-to-add-a-module.md). diff --git a/how-to/workspace-platform-starter/public/schemas/fdc3v1.2-appd.schema.json b/how-to/workspace-platform-starter/public/schemas/fdc3v1.2-appd.schema.json index 61073b13a9..5550af8201 100644 --- a/how-to/workspace-platform-starter/public/schemas/fdc3v1.2-appd.schema.json +++ b/how-to/workspace-platform-starter/public/schemas/fdc3v1.2-appd.schema.json @@ -315,6 +315,20 @@ "additionalProperties": false, "description": "Additional options that apply to a native app", "properties": { + "native": { + "additionalProperties": false, + "description": "Launch Preferences related to native apps", + "properties": { + "arguments": { + "description": "Arguments are set as an array for compatibility with appAssets, launchExternalProcess and Snap.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "snap": { "$ref": "#/definitions/SnapLaunchOptions", "description": "If specified it indicates the native app should be included when snapping." @@ -323,11 +337,35 @@ "const": "native", "description": "Native options type", "type": "string" + }, + "updatable": { + "description": "What can be specified when launching a native app. This is an array of named types to reflect the properties you are happy to be specified.\nBy default nothing can be set outside of the app definition when launching the app.", + "items": { + "$ref": "#/definitions/NativePreference" + }, + "type": "array" } }, "required": ["type"], "type": "object" }, + "NativePreference": { + "additionalProperties": false, + "description": "Which Launch Options are updatable and are there any constraints", + "properties": { + "name": { + "$ref": "#/definitions/NativePreferenceName", + "description": "What setting is updatable?" + } + }, + "required": ["name"], + "type": "object" + }, + "NativePreferenceName": { + "const": "arguments", + "description": "A list of native related settings that can be updated.", + "type": "string" + }, "Partial": { "$ref": "#/definitions/__type" }, @@ -343,13 +381,6 @@ "additionalProperties": false, "description": "Additional options that apply to the app when used in a snap context", "properties": { - "args": { - "description": "Snap requires args as a string array, not a single string like in app assets.\nSo we provide the ability to include them here.", - "items": { - "type": "string" - }, - "type": "array" - }, "strategy": { "$ref": "#/definitions/LaunchStrategy", "description": "The strategy for launching and locating the application." diff --git a/how-to/workspace-platform-starter/public/schemas/fdc3v2.0-appd.schema.json b/how-to/workspace-platform-starter/public/schemas/fdc3v2.0-appd.schema.json index 3f99381a06..604d2b95ae 100644 --- a/how-to/workspace-platform-starter/public/schemas/fdc3v2.0-appd.schema.json +++ b/how-to/workspace-platform-starter/public/schemas/fdc3v2.0-appd.schema.json @@ -491,6 +491,20 @@ "additionalProperties": false, "description": "Additional options that apply to a native app", "properties": { + "native": { + "additionalProperties": false, + "description": "Launch Preferences related to native apps", + "properties": { + "arguments": { + "description": "Arguments are set as an array for compatibility with appAssets, launchExternalProcess and Snap.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "snap": { "$ref": "#/definitions/SnapLaunchOptions", "description": "If specified it indicates the native app should be included when snapping." @@ -499,11 +513,35 @@ "const": "native", "description": "Native options type", "type": "string" + }, + "updatable": { + "description": "What can be specified when launching a native app. This is an array of named types to reflect the properties you are happy to be specified.\nBy default nothing can be set outside of the app definition when launching the app.", + "items": { + "$ref": "#/definitions/NativePreference" + }, + "type": "array" } }, "required": ["type"], "type": "object" }, + "NativePreference": { + "additionalProperties": false, + "description": "Which Launch Options are updatable and are there any constraints", + "properties": { + "name": { + "$ref": "#/definitions/NativePreferenceName", + "description": "What setting is updatable?" + } + }, + "required": ["name"], + "type": "object" + }, + "NativePreferenceName": { + "const": "arguments", + "description": "A list of native related settings that can be updated.", + "type": "string" + }, "OnlineNativeAppDetails": { "additionalProperties": false, "description": "Online native application details.", @@ -560,13 +598,6 @@ "additionalProperties": false, "description": "Additional options that apply to the app when used in a snap context", "properties": { - "args": { - "description": "Snap requires args as a string array, not a single string like in app assets.\nSo we provide the ability to include them here.", - "items": { - "type": "string" - }, - "type": "array" - }, "strategy": { "$ref": "#/definitions/LaunchStrategy", "description": "The strategy for launching and locating the application." diff --git a/how-to/workspace-platform-starter/public/schemas/platform-apps.schema.json b/how-to/workspace-platform-starter/public/schemas/platform-apps.schema.json index 40207d948b..c42ee2b577 100644 --- a/how-to/workspace-platform-starter/public/schemas/platform-apps.schema.json +++ b/how-to/workspace-platform-starter/public/schemas/platform-apps.schema.json @@ -384,6 +384,20 @@ "additionalProperties": false, "description": "Additional options that apply to a native app", "properties": { + "native": { + "additionalProperties": false, + "description": "Launch Preferences related to native apps", + "properties": { + "arguments": { + "description": "Arguments are set as an array for compatibility with appAssets, launchExternalProcess and Snap.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "snap": { "$ref": "#/definitions/SnapLaunchOptions", "description": "If specified it indicates the native app should be included when snapping." @@ -392,11 +406,35 @@ "const": "native", "description": "Native options type", "type": "string" + }, + "updatable": { + "description": "What can be specified when launching a native app. This is an array of named types to reflect the properties you are happy to be specified.\nBy default nothing can be set outside of the app definition when launching the app.", + "items": { + "$ref": "#/definitions/NativePreference" + }, + "type": "array" } }, "required": ["type"], "type": "object" }, + "NativePreference": { + "additionalProperties": false, + "description": "Which Launch Options are updatable and are there any constraints", + "properties": { + "name": { + "$ref": "#/definitions/NativePreferenceName", + "description": "What setting is updatable?" + } + }, + "required": ["name"], + "type": "object" + }, + "NativePreferenceName": { + "const": "arguments", + "description": "A list of native related settings that can be updated.", + "type": "string" + }, "Partial": { "$ref": "#/definitions/__type" }, @@ -628,13 +666,6 @@ "additionalProperties": false, "description": "Additional options that apply to the app when used in a snap context", "properties": { - "args": { - "description": "Snap requires args as a string array, not a single string like in app assets.\nSo we provide the ability to include them here.", - "items": { - "type": "string" - }, - "type": "array" - }, "strategy": { "$ref": "#/definitions/LaunchStrategy", "description": "The strategy for launching and locating the application." diff --git a/how-to/workspace-platform-starter/public/schemas/settings.schema.json b/how-to/workspace-platform-starter/public/schemas/settings.schema.json index b3276991ba..66838709a6 100644 --- a/how-to/workspace-platform-starter/public/schemas/settings.schema.json +++ b/how-to/workspace-platform-starter/public/schemas/settings.schema.json @@ -3087,6 +3087,20 @@ "additionalProperties": false, "description": "Additional options that apply to a native app", "properties": { + "native": { + "additionalProperties": false, + "description": "Launch Preferences related to native apps", + "properties": { + "arguments": { + "description": "Arguments are set as an array for compatibility with appAssets, launchExternalProcess and Snap.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "snap": { "$ref": "#/definitions/SnapLaunchOptions", "description": "If specified it indicates the native app should be included when snapping." @@ -3095,6 +3109,13 @@ "const": "native", "description": "Native options type", "type": "string" + }, + "updatable": { + "description": "What can be specified when launching a native app. This is an array of named types to reflect the properties you are happy to be specified.\nBy default nothing can be set outside of the app definition when launching the app.", + "items": { + "$ref": "#/definitions/NativePreference" + }, + "type": "array" } }, "required": [ @@ -3102,6 +3123,25 @@ ], "type": "object" }, + "NativePreference": { + "additionalProperties": false, + "description": "Which Launch Options are updatable and are there any constraints", + "properties": { + "name": { + "$ref": "#/definitions/NativePreferenceName", + "description": "What setting is updatable?" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "NativePreferenceName": { + "const": "arguments", + "description": "A list of native related settings that can be updated.", + "type": "string" + }, "NotificationClientDefaultOptions": { "additionalProperties": false, "description": "A set of default options that will apply against all notification clients unless they\nhave a setting of their own.", @@ -3941,13 +3981,6 @@ "additionalProperties": false, "description": "Additional options that apply to the app when used in a snap context", "properties": { - "args": { - "description": "Snap requires args as a string array, not a single string like in app assets.\nSo we provide the ability to include them here.", - "items": { - "type": "string" - }, - "type": "array" - }, "strategy": { "$ref": "#/definitions/LaunchStrategy", "description": "The strategy for launching and locating the application." diff --git a/package-lock.json b/package-lock.json index e8a387e555..f8771dd6de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2549,9 +2549,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -5623,9 +5623,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz", - "integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==", + "version": "20.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.2.tgz", + "integrity": "sha512-37MXfxkb0vuIlRKHNxwCkb60PNBpR94u4efQuN4JgIAm66zfCDXGSAFCef9XUWFovX2R1ok6Z7MHhtdVXXkkIw==", "dependencies": { "undici-types": "~5.26.4" } @@ -5659,9 +5659,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.39", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz", - "integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==", + "version": "18.2.40", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.40.tgz", + "integrity": "sha512-H+BUhb9C1zBtogDLAk+KCNRKiHDrqSwQT/0z0PVTwMFBxqg3011ByLomADtgkgMkfwj4AMOiXBReyLTUBg681g==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -7131,9 +7131,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1509.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1509.0.tgz", - "integrity": "sha512-5h27GXv5/M1Cfgw5StYqTyCesnqscez3QOsKGnShCXP6saGkSEvV3TUHTXQBqdfsrBmz5hVCa8doqP3r3yJD/w==", + "version": "2.1510.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1510.0.tgz", + "integrity": "sha512-XQj3QINBNseA5G9Vaa/iihNz3HCrzeyhxrOUjuH0AVxYqa5Q4cxaQhrWiAiUndtO2F70nfukEYe4cCUoTalUoQ==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -9563,9 +9563,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.600", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.600.tgz", - "integrity": "sha512-KD6CWjf1BnQG+NsXuyiTDDT1eV13sKuYsOUioXkQweYTQIbgHkXPry9K7M+7cKtYHnSUPitVaLrXYB1jTkkYrw==" + "version": "1.4.601", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz", + "integrity": "sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==" }, "node_modules/emittery": { "version": "0.13.1", @@ -18658,9 +18658,9 @@ } }, "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", - "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.3.tgz", + "integrity": "sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==", "dev": true, "engines": { "node": ">=16" @@ -18767,9 +18767,9 @@ } }, "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", - "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.3.tgz", + "integrity": "sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==", "dev": true, "engines": { "node": ">=16" @@ -20457,13 +20457,13 @@ "dev": true }, "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", + "integrity": "sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==", "dev": true, "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" + "@pkgr/utils": "^2.4.2", + "tslib": "^2.6.2" }, "engines": { "node": "^14.18.0 || >=16.0.0"