Skip to content

Commit e5449d7

Browse files
Add various utility functions
Signed-off-by: Andrei Floricel <andrei.floricel@gmail.com>
1 parent a19a633 commit e5449d7

6 files changed

Lines changed: 164 additions & 2 deletions

File tree

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@
99
website
1010
dist
1111
src/app-directory/*/target
12+
13+
# temporary, until Prettier is upgraded to at least v2.8, which supports the TS 'satisfies' syntax
14+
src/**/IntentsConfiguration.ts

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/Methods.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import {
1515
AppMetadata,
1616
PrivateChannel,
1717
Intent,
18+
StandardContextType,
19+
StandardIntent,
20+
ContextTypeFor,
1821
} from '..';
22+
import { IntentsConfiguration, StandardContextsSet, StandardIntentsSet } from '../intents/IntentsConfiguration';
1923

2024
const DEFAULT_TIMEOUT = 5000;
2125

@@ -179,6 +183,30 @@ export function findInstances(app: AppIdentifier): Promise<AppIdentifier[]> {
179183
return rejectIfNoGlobal(() => window.fdc3.findInstances(app));
180184
}
181185

186+
/**
187+
* Check if the given context is a standard context type.
188+
* @param contextType
189+
*/
190+
export function isStandardContextType(contextType: string): contextType is StandardContextType {
191+
return StandardContextsSet.has(contextType as StandardContextType);
192+
}
193+
194+
/**
195+
* Check if the given intent is a standard intent.
196+
* @param intent
197+
*/
198+
export function isStandardIntent(intent: string): intent is StandardIntent {
199+
return StandardIntentsSet.has(intent as StandardIntent);
200+
}
201+
202+
/**
203+
* Get the possible context types for a given intent.
204+
* @param intent
205+
*/
206+
export function getPossibleContextsForIntent<I extends StandardIntent>(intent: I): ContextTypeFor<I>[] {
207+
return IntentsConfiguration[intent] ?? [];
208+
}
209+
182210
/**
183211
* Compare numeric semver version number strings (in the form `1.2.3`).
184212
*

src/intents/Intents.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright FINOS FDC3 contributors - see NOTICE file
44
*/
55

6+
import { IntentsConfiguration } from './IntentsConfiguration';
7+
68
/**
79
* @see https://fdc3.finos.org/docs/intents/spec#standard-intents
810
*/
@@ -30,3 +32,10 @@ export type StandardIntent =
3032
* @see https://fdc3.finos.org/docs/intents/spec
3133
*/
3234
export type Intent = StandardIntent | (string & {});
35+
36+
/**
37+
* Typed possible context for a given intent
38+
*
39+
* @example `ContextTypeFor<'StartCall'>` is equivalent to `'fdc3.contact' | 'fdc3.contactList' | 'fdc3.nothing'`
40+
*/
41+
export type ContextTypeFor<I extends StandardIntent> = typeof IntentsConfiguration[I][number];
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { StandardIntent } from './Intents';
2+
import { StandardContextType } from '../context/ContextType';
3+
4+
export const IntentsConfiguration = {
5+
CreateInteraction: ['fdc3.contactList', 'fdc3.interaction', 'fdc3.nothing'],
6+
StartCall: ['fdc3.contact', 'fdc3.contactList', 'fdc3.nothing'],
7+
StartChat: ['fdc3.contact', 'fdc3.contactList', 'fdc3.chat.initSettings', 'fdc3.nothing'],
8+
StartEmail: ['fdc3.email', 'fdc3.nothing'],
9+
SendChatMessage: ['fdc3.chat.message', 'fdc3.nothing'],
10+
ViewAnalysis: ['fdc3.instrument', 'fdc3.organization', 'fdc3.portfolio', 'fdc3.nothing'],
11+
ViewChat: ['fdc3.chat.room', 'fdc3.contact', 'fdc3.contactList', 'fdc3.nothing'],
12+
ViewChart: [
13+
'fdc3.chart',
14+
'fdc3.instrument',
15+
'fdc3.instrumentList',
16+
'fdc3.portfolio',
17+
'fdc3.position',
18+
'fdc3.nothing',
19+
],
20+
ViewContact: ['fdc3.contact', 'fdc3.nothing'],
21+
ViewHoldings: ['fdc3.instrument', 'fdc3.instrumentList', 'fdc3.organization', 'fdc3.nothing'],
22+
ViewInstrument: ['fdc3.instrument', 'fdc3.nothing'],
23+
ViewInteractions: ['fdc3.contact', 'fdc3.instrument', 'fdc3.organization', 'fdc3.nothing'],
24+
ViewMessages: ['fdc3.chat.searchCriteria', 'fdc3.nothing'],
25+
ViewNews: [
26+
'fdc3.country',
27+
'fdc3.instrument',
28+
'fdc3.instrumentList',
29+
'fdc3.organization',
30+
'fdc3.portfolio',
31+
'fdc3.nothing',
32+
],
33+
ViewOrders: ['fdc3.contact', 'fdc3.instrument', 'fdc3.organization', 'fdc3.nothing'],
34+
ViewProfile: ['fdc3.contact', 'fdc3.organization', 'fdc3.nothing'],
35+
ViewQuote: ['fdc3.instrument', 'fdc3.nothing'],
36+
ViewResearch: ['fdc3.contact', 'fdc3.instrument', 'fdc3.organization', 'fdc3.nothing'],
37+
} satisfies Record<StandardIntent, StandardContextType[]>;
38+
39+
const STANDARD_CONTEXT_TYPES: Readonly<StandardContextType[]> = [
40+
'fdc3.action',
41+
'fdc3.chart',
42+
'fdc3.chat.initSettings',
43+
'fdc3.chat.message',
44+
'fdc3.chat.room',
45+
'fdc3.chat.searchCriteria',
46+
'fdc3.contact',
47+
'fdc3.contactList',
48+
'fdc3.country',
49+
'fdc3.currency',
50+
'fdc3.email',
51+
'fdc3.instrument',
52+
'fdc3.instrumentList',
53+
'fdc3.interaction',
54+
'fdc3.message',
55+
'fdc3.organization',
56+
'fdc3.portfolio',
57+
'fdc3.position',
58+
'fdc3.nothing',
59+
'fdc3.timerange',
60+
'fdc3.transactionResult',
61+
'fdc3.valuation',
62+
] as const;
63+
64+
// used internally to check if a given intent/context is a standard one
65+
export const StandardIntentsSet = new Set(Object.keys(IntentsConfiguration) as StandardIntent[]);
66+
export const StandardContextsSet = new Set(STANDARD_CONTEXT_TYPES);

test/Methods.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
versionIsAtLeast,
2626
createPrivateChannel,
2727
findInstances,
28+
isStandardContextType,
29+
isStandardIntent,
2830
} from '../src';
2931

3032
const UnavailableError = new Error('FDC3 DesktopAgent not available at `window.fdc3`.');
@@ -443,4 +445,58 @@ describe('test version comparison functions', () => {
443445
expect(versionIsAtLeast(metaOneTwoOne, '1.2.1')).toBe(true);
444446
expect(versionIsAtLeast(metaOneTwoOne, '2.0')).toBe(false);
445447
});
448+
449+
test('isStandardContextType should return TRUE for standard context types', () => {
450+
expect(isStandardContextType('fdc3.action')).toBe(true);
451+
expect(isStandardContextType('fdc3.chart')).toBe(true);
452+
expect(isStandardContextType('fdc3.chat.initSettings')).toBe(true);
453+
expect(isStandardContextType('fdc3.chat.message')).toBe(true);
454+
expect(isStandardContextType('fdc3.chat.room')).toBe(true);
455+
expect(isStandardContextType('fdc3.chat.searchCriteria')).toBe(true);
456+
expect(isStandardContextType('fdc3.contact')).toBe(true);
457+
expect(isStandardContextType('fdc3.contactList')).toBe(true);
458+
expect(isStandardContextType('fdc3.country')).toBe(true);
459+
expect(isStandardContextType('fdc3.currency')).toBe(true);
460+
expect(isStandardContextType('fdc3.email')).toBe(true);
461+
expect(isStandardContextType('fdc3.instrument')).toBe(true);
462+
expect(isStandardContextType('fdc3.instrumentList')).toBe(true);
463+
expect(isStandardContextType('fdc3.interaction')).toBe(true);
464+
expect(isStandardContextType('fdc3.message')).toBe(true);
465+
expect(isStandardContextType('fdc3.organization')).toBe(true);
466+
expect(isStandardContextType('fdc3.portfolio')).toBe(true);
467+
expect(isStandardContextType('fdc3.position')).toBe(true);
468+
expect(isStandardContextType('fdc3.nothing')).toBe(true);
469+
expect(isStandardContextType('fdc3.timerange')).toBe(true);
470+
expect(isStandardContextType('fdc3.transactionResult')).toBe(true);
471+
expect(isStandardContextType('fdc3.valuation')).toBe(true);
472+
});
473+
474+
test('isStandardContextType should return FALSE for custom context types', () => {
475+
expect(isStandardContextType('myApp.customContext')).toBe(false);
476+
});
477+
478+
test('isStandardIntent should return TRUE for standard intents', () => {
479+
expect(isStandardIntent('CreateInteraction')).toBe(true);
480+
expect(isStandardIntent('SendChatMessage')).toBe(true);
481+
expect(isStandardIntent('StartCall')).toBe(true);
482+
expect(isStandardIntent('StartChat')).toBe(true);
483+
expect(isStandardIntent('StartEmail')).toBe(true);
484+
expect(isStandardIntent('ViewAnalysis')).toBe(true);
485+
expect(isStandardIntent('ViewChat')).toBe(true);
486+
expect(isStandardIntent('ViewChart')).toBe(true);
487+
expect(isStandardIntent('ViewContact')).toBe(true);
488+
expect(isStandardIntent('ViewHoldings')).toBe(true);
489+
expect(isStandardIntent('ViewInstrument')).toBe(true);
490+
expect(isStandardIntent('ViewInteractions')).toBe(true);
491+
expect(isStandardIntent('ViewMessages')).toBe(true);
492+
expect(isStandardIntent('ViewNews')).toBe(true);
493+
expect(isStandardIntent('ViewOrders')).toBe(true);
494+
expect(isStandardIntent('ViewProfile')).toBe(true);
495+
expect(isStandardIntent('ViewQuote')).toBe(true);
496+
expect(isStandardIntent('ViewResearch')).toBe(true);
497+
});
498+
499+
test('isStandardIntent should return FALSE for custom intents', () => {
500+
expect(isStandardIntent('myApp.CustomIntent')).toBe(false);
501+
});
446502
});

0 commit comments

Comments
 (0)