Skip to content

Commit

Permalink
Documentation, improved options
Browse files Browse the repository at this point in the history
  • Loading branch information
robmoffat committed Jul 10, 2024
1 parent fad951c commit afcfd4d
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 14 deletions.
14 changes: 14 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
plugins: ['@typescript-eslint/eslint-plugin', 'eslint-plugin-tsdoc'],
extends: ['plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
ecmaVersion: 2018,
sourceType: 'module'
},
rules: {
'tsdoc/syntax': 'warn'
}
};
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@
"clean": "yarn workspaces foreach --all run clean",
"build": "yarn workspaces foreach --all run build",
"test": "yarn workspaces foreach --all run test",
"dev": "concurrently \"cd packages/addon && yarn dev\" \"cd packages/fdc3-workbench && yarn dev\" \"cd packages/demo && yarn dev\""
"dev": "concurrently \"cd packages/addon && yarn dev\" \"cd packages/fdc3-workbench && yarn dev\" \"cd packages/demo && yarn dev\"",
"docs": "yarn typedocs --out docs packages/fdc3-common/index.ts /packages/client/**"
},
"packageManager": "[email protected]",
"devDependencies": {
"concurrently": "8.2.2",
"eslint": "7.17.0",
"prettier": "2.2.1",
"rimraf": "^5.0.7",
"typedoc": "^0.26.4",
"typescript": "^5.3.2"
},
"publishConfig": {
"registry": "https://registry.npmjs.org"
}
}
}
43 changes: 37 additions & 6 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { DesktopAgent } from '@finos/fdc3'
import { Options } from '@kite9/fdc3-common';
import fail from './strategies/fail';
import electronEvent from './strategies/electron-event'
import postMessage from './strategies/post-message'
//import electronEvent from './strategies/electron-event'

const DEFAULT_WAIT_FOR_MS = 20000;

export const DEFAULT_OPTIONS: Options = {
setWindowGlobal: false,
fireFdc3Ready: false,
strategies: [postMessage], //, electronEvent],
strategies: [postMessage, electronEvent],
frame: window.opener ?? window.parent,
waitForMs: DEFAULT_WAIT_FOR_MS,
}

/**
* This return an FDC3 API. Called by Apps.
* This return an FDC3 API. Should be called by application code.
*
* @param optionsOverride - options to override the default options
*/
export function getClientAPI(optionsOverride: Options = DEFAULT_OPTIONS): Promise<DesktopAgent> {

Expand All @@ -25,16 +31,41 @@ export function getClientAPI(optionsOverride: Options = DEFAULT_OPTIONS): Promis
window.fdc3 = da;
}

if (options.fireFdc3Ready) {
window.dispatchEvent(new Event("fdc3Ready"));
}

sessionStorage.setItem("fdc3", "true");

return da;
}

const strategies = options.strategies!!.map(s => s(options));
function waitThenFallback(options: Options): Promise<DesktopAgent> {
const fallbackStrategy = options.fallbackStrategy ?? fail

return new Promise<DesktopAgent>((_, reject) => {
setTimeout(() => reject(new Error('timeout succeeded')), options.waitForMs);
}).then(() => fallbackStrategy(options))
}

const toProcess = [
...options.strategies!!,
waitThenFallback
]

const strategies = toProcess.map(s => s(options));

return Promise.any(strategies)
return Promise.race(strategies)
.then(da => handleGenericOptions(da))
}

export function fdc3Ready(waitForMs?: number): Promise<DesktopAgent> {
/**
* Replaces the original fdc3Ready function from FDC3 2.0 with a new one that uses the new getClientAPI function.
*
* @param waitForMs Amount of time to wait before failing the promise (20 seconds is the default).
* @returns A DesktopAgent promise.
*/
export function fdc3Ready(waitForMs = DEFAULT_WAIT_FOR_MS): Promise<DesktopAgent> {
return getClientAPI({
...DEFAULT_OPTIONS,
waitForMs,
Expand Down
13 changes: 13 additions & 0 deletions packages/client/src/strategies/fail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Loader, Options } from "@kite9/fdc3-common";

/**
* This is the default fallback strategy which just throws an
* error because the desktop agent can't be found.
*/
const fail: Loader = (_options: Options) => {

throw new Error("No desktop agent found");

}

export default fail
Empty file added packages/client/test/features
Empty file.
4 changes: 2 additions & 2 deletions packages/demo/src/client/da/dummy-desktop-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ window.addEventListener("load", () => {
socket.emit(DA_HELLO, desktopAgentUUID)

const directory = new FDC3_2_1_JSONDirectory()
await directory.load("/static/da/appd.json")
//await directory.load("/static/da/local-conformance-2_0.v2.json")
//await directory.load("/static/da/appd.json")
await directory.load("/static/da/local-conformance-2_0.v2.json")
const sc = new DemoServerContext(socket, directory, desktopAgentUUID)
const initialChannels: ChannelState = {
"one": [],
Expand Down
50 changes: 47 additions & 3 deletions packages/fdc3-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,52 @@ import { AppIntent, PrivateChannelOnAddContextListenerAgentRequest, PrivateChann
* We need to add options here.
*/
export type Options = {
/**
* Set this true if you wish to have window.fdc3 set to the desktop agent once it is found
*/
setWindowGlobal?: boolean,
/**
* Set this to true if you want to fire an fdc3.ready event on the window. This is for backwards compatibility with FDC3 2.0 and the old
* window.fdc3 approach.
*/
fireFdc3Ready?: boolean,

/**
* Override this if you want to customise the loaders used. By default, it will use the postMessage and electronEvent strategies.
*/
strategies?: Loader[],

/**
* Override this if you want to supply your own fallback approach for getting the FDC3 api. By default, it will throw an error.
*/
fallbackStrategy?: Loader,

/**
* This is the frame/window that the desktop agent should be found in. By default, it will use the opener or parent window.
*/
frame?: Window,

/**
* This is the time to wait for the strategies to find a desktop agent. By default, it is 20 seconds.
*/
waitForMs?: number,

/**
* If you wish to opt-out of the desktop agent's own intent resolver and supply an implementation, do so here.
*/
intentResolver?: IntentResolver,
channelSelector?: ChannelSelector

/**
* If you wish to opt-out of the desktop agent's own channel selector and supply an implementation, do so here.
*/
channelSelector?: ChannelSelector,

/**
* The initial path is used by the desktop to check that it is talking to the right application when applications share the same origin.
* If the application tries to load the desktop agent from a window with a different URL from the one provided to the desktop agent in the app
* directory, you'll need to set it here.
*/
appInitialPath?: string
}


Expand Down Expand Up @@ -165,7 +204,9 @@ export interface SingleAppIntent {

export type ChannelState = { [channelId: string]: ContextElement[] }


/**
* Interface used by the desktop agent proxy to handle the channel selection process.
*/
export interface ChannelSelector {

updateChannel(channelId: string | null, availableChannels: Channel[]): void
Expand All @@ -174,10 +215,13 @@ export interface ChannelSelector {

}

/**
* Interface used by the desktop agent proxy to handle the intent resolution process.
*/
export interface IntentResolver {

/**
* Called when the user needs to resolve an intent
* Called when the user needs to resolve an intent.
*/
chooseIntent(appIntents: AppIntent[], source: AppIdentifier): Promise<SingleAppIntent>

Expand Down
Loading

0 comments on commit afcfd4d

Please sign in to comment.