Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d9541d1
Context Clearing
kemerava Sep 27, 2024
77e2b61
Apply suggestions from code review
kemerava Oct 4, 2024
a2c348e
Changelog and fixing the name of the field
kemerava Oct 4, 2024
60456c3
Merge remote-tracking branch 'origin/main' into feature/context-clearing
kemerava Dec 11, 2024
768f50d
Adding conformance tests
kemerava Dec 11, 2024
acac1a0
Apply suggestions from code review
kemerava Jan 31, 2025
a4106fe
Merge remote-tracking branch 'origin/main' into feature/context-clearing
kemerava Mar 21, 2025
4e2bc61
Merge branch 'main' into feature/context-clearing
kriswest Apr 17, 2025
c66f420
Merge remote-tracking branch 'origin/main' into feature/context-clearing
kemerava May 8, 2025
cdeea6a
Adding addEventListener for listening on clearing context
kemerava May 8, 2025
1ad0c4a
Clearing context tests
kemerava May 8, 2025
a732bcc
Fixing package-lock.json
kemerava May 14, 2025
9c79048
Making build pass
kemerava Jun 20, 2025
04507e0
Merge remote-tracking branch 'origin/main' into feature/context-clearing
kemerava Jul 9, 2025
e21ec30
Adding the event for the contextCleared
kemerava Jul 9, 2025
90c8fab
npm
kemerava Jul 9, 2025
c63e1d4
PR review changes
kemerava Jul 9, 2025
b953954
Merge remote-tracking branch 'origin/main' into feature/context-clearing
kemerava Jul 25, 2025
bc5c98c
Update CHANGELOG.md
kemerava Jul 25, 2025
c572444
Merge branch 'feature/context-clearing' of https://github.com/kemerav…
kemerava Jul 25, 2025
90a06e3
Update website/docs/api/ref/Channel.md
kemerava Jul 25, 2025
ac73c5c
Updating based on reviews
kemerava Jul 25, 2025
6d22fb3
Typo
kemerava Jul 25, 2025
a7e5c4b
Update lang
kemerava Jul 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

* Added details of and procedures for resolving fully-qualified appIds and unqualified appIds in the API and Bridging Parts of the Standard. ([#1523](https://github.com/finos/FDC3/pull/1523))

* Added `clearContext` function to the `Channel` API, to be able to clear specific or all context types from the channel. ([#1379](https://github.com/finos/FDC3/pull/1379))

### Changed

### Deprecated
Expand Down Expand Up @@ -50,6 +52,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added .NET docs for Events to API reference. ([#1441](https://github.com/finos/FDC3/pull/1441))
* Setup package publishing for mono-repo packages. ([#1520](https://github.com/finos/FDC3/pull/1520))
* Implementation PR for FDC3 for the Web ([#896](https://github.com/finos/FDC3/pull/896))
- resolves ([#1209](https://github.com/finos/FDC3/issues/1209))
- resolves ([#1297](https://github.com/finos/FDC3/issues/1297))
- resolves ([#1429](https://github.com/finos/FDC3/issues/1429))
- resolves ([#1430](https://github.com/finos/FDC3/issues/1430))
- resolves ([#1431](https://github.com/finos/FDC3/issues/1431))
- resolves ([#1432](https://github.com/finos/FDC3/issues/1432))
- resolves ([#1433](https://github.com/finos/FDC3/issues/1433))
- resolves ([#1468](https://github.com/finos/FDC3/issues/1468))
- resolves ([#810](https://github.com/finos/FDC3/issues/810))
- resolves ([#832](https://github.com/finos/FDC3/issues/832))
- resolves ([#1487](https://github.com/finos/FDC3/issues/1487))
- resolves ([#1488](https://github.com/finos/FDC3/issues/1488))
* Adjusted reference Desktop Agent implementation for FDC3 for Web to open a new app instance when raiseIntent is called with an appId but no instanceId ([#1556](https://github.com/finos/FDC3/pull/1556))

### Changed
Expand Down
38 changes: 7 additions & 31 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion packages/fdc3-agent-proxy/src/channels/DefaultChannel.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { ContextHandler, DisplayMetadata, Listener, Channel } from '@finos/fdc3-standard';
import { ContextHandler, DisplayMetadata, Listener, Channel, EventHandler } from '@finos/fdc3-standard';
import { Context } from '@finos/fdc3-context';
import { Messaging } from '../Messaging';
import { DefaultContextListener } from '../listeners/DefaultContextListener';
import {
BroadcastRequest,
BroadcastResponse,
ClearContextRequest,
ClearContextResponse,
GetCurrentContextRequest,
GetCurrentContextResponse,
} from '@finos/fdc3-schema/generated/api/BrowserTypes';
import { RegisterableListener } from '../listeners/RegisterableListener';
import { EventListener } from '../listeners/EventListener';

export class DefaultChannel implements Channel {
protected readonly messaging: Messaging;
Expand Down Expand Up @@ -98,4 +102,30 @@ export class DefaultChannel implements Channel {
await listener.register();
return listener;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're going to need some cucumber tests for this otherwise you'll see the coverage dip!

async clearContext(contextType?: string): Promise<void> {
// first, ensure channel state is up-to-date
const request: ClearContextRequest = {
meta: this.messaging.createMeta(),
payload: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there will need to be support for this event added to the BroadcastHandler in the fdc3-web-impl, plus tests of the same there.

channelId: this.id,
contextType: contextType ?? null,
},
type: 'clearContextRequest',
};
await this.messaging.exchange<ClearContextResponse>(request, 'clearContextResponse', this.messageExchangeTimeout);
}

async addEventListener(type: string | null, handler: EventHandler): Promise<Listener> {
let listener: RegisterableListener;
switch (type) {
case 'contextCleared':
listener = new EventListener(this.messaging, 'contextCleared', handler);
break;
Copy link

Copilot AI Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addEventListener implementation throws on null event type, but the API allows subscribing to all events with null. Consider handling null to register a listener for all event types.

Suggested change
break;
break;
case null:
listener = new EventListener(this.messaging, 'allEvents', handler); // Register for all events
break;

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot has a point there. It looks like this is also wrong where we listener for the channelChanged event:

addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise<Listener> {
switch (type) {
case 'userChannelChanged':
return this.channels.addChannelChangedEventHandler(handler);
default:
Logger.warn(`Tried to add a listener for an unknown event type: ${type}`);
return Promise.reject(new Error('UnknownEventType'));
}
}

Co-pilot's suggestion to fix isn't right however. Rather EventListener will probbably ned to be adjusted to be able to take multiple types:

constructor(messaging: Messaging, type: string, handler: EventHandler) {

As we need to know the specific messages it should respond to (from a set that is wider than the scope of the listener).

default:
throw new Error('Unsupported event type: ' + type);
}
await listener.register();
return listener;
}
}
3 changes: 2 additions & 1 deletion packages/fdc3-schema/schemas/api/agentResponse.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"privateChannelUnsubscribeEventListenerResponse",
"raiseIntentForContextResponse",
"raiseIntentResponse",
"raiseIntentResultResponse"
"raiseIntentResultResponse",
"clearContextResponse"
],
"description": "Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Response' appended."
},
Expand Down
3 changes: 2 additions & 1 deletion packages/fdc3-schema/schemas/api/appRequest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"privateChannelDisconnectRequest",
"privateChannelUnsubscribeEventListenerRequest",
"raiseIntentForContextRequest",
"raiseIntentRequest"
"raiseIntentRequest",
"clearContextRequest"
],
"description": "Identifies the type of the message and it is typically set to the FDC3 function name that the message relates to, e.g. 'findIntent', with 'Request' appended."
},
Expand Down
56 changes: 56 additions & 0 deletions packages/fdc3-schema/schemas/api/clearContextRequest.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://fdc3.finos.org/schemas/next/api/clearContextRequest.schema.json",
"type": "object",
"title": "Clear Context Request",
"description": "A request to clear context on a channel.",
"allOf": [
{
"$ref": "appRequest.schema.json"
},
{
"type": "object",
"properties": {
"type": {
"$ref": "#/$defs/ClearContextRequestType"
},
"payload": {
"$ref": "#/$defs/ClearContextRequestPayload"
},
"meta": true
},
"additionalProperties": false
}
],
"$defs": {
"ClearContextRequestType": {
"title": "Clear Context Request Message Type",
"const": "clearContextRequest"
},
"ClearContextRequestPayload": {
"title": "Clear Context Request Payload",
"type": "object",
"properties": {
"channelId": {
"title": "Channel Id",
"description": "The id of the channel to clear the context on.",
"type": "string"
},
"contextType": {
"title": "Context type",
"description": "The type of context to clear for OR `null` indicating that all context types on the channel should be cleared.",
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": ["channelId", "contextType"],
"additionalProperties": false
}
}
}
29 changes: 29 additions & 0 deletions packages/fdc3-schema/schemas/api/clearContextResponse.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://fdc3.finos.org/schemas/next/api/clearContextResponse.schema.json",
"type": "object",
"title": "Clear Context Response",
"description": "A response to a request to clear context on a channel.",
"allOf": [
{
"$ref": "agentResponse.schema.json"
},
{
"type": "object",
"properties": {
"type": {
"$ref": "#/$defs/ClearContextResponseType"
},
"payload": true,
"meta": true
},
"additionalProperties": false
}
],
"$defs": {
"ClearContextResponseType": {
"title": "Clear Context Response Message Type",
"const": "clearContextResponse"
}
}
}
33 changes: 33 additions & 0 deletions packages/fdc3-standard/src/api/Channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { ContextHandler } from './Types';
import { DisplayMetadata } from './DisplayMetadata';
import { Listener } from './Listener';
import { EventHandler } from './Events';

/**
* Represents a context channel that applications can use to send and receive
Expand Down Expand Up @@ -73,8 +74,40 @@
*/
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;

/**
* Clears context from the channel, and broadcasts an `fdc3.nothing` context to notify existing listeners that the context was cleared. Listeners added to the channel and calls to [`getCurrentContext`](#getcurrentcontext) will not receive any existing context until new context is broadcast to the channel.
*
* If a `contextType` is provided, only contexts of that type will be cleared and the `contextType` of the `fdc3.nothing` context will be set to that type name.
*
* If no `contextType` is provided, all contexts will be cleared and the `contextType` of the `fdc3.nothing` context will be omitted.
*/
clearContext(contextType?: string): Promise<void>;

/**
* Register a handler for events from the Channel. Whenever the handler function
* is called it will be passed an event object with details related to the event.
*
* ```js
* // any event type
* const listener = await myChannel.addEventListener(null, event => {
* console.log(`Received event ${event.type}\n\tDetails: ${event.details}`);
* });
*
* // listener for a specific event type
* const contextClearedListener = await myChannel.addEventListener(
* "contextCleared",
* event => { ... }
* );
* ```
*
* @param {string | null} type If non-null, only events of the specified type will be received by the handler.
* @param {EventHandler} handler A function that events received will be passed to.
*
*/
addEventListener(type: string | null, handler: EventHandler): Promise<Listener>;

/**
* @deprecated use `addContextListener(null, handler)` instead of `addContextListener(handler)`.
*/
addContextListener(handler: ContextHandler): Promise<Listener>;

Check warning on line 112 in packages/fdc3-standard/src/api/Channel.ts

View workflow job for this annotation

GitHub Actions / test

All addContextListener signatures should be adjacent
}
10 changes: 10 additions & 0 deletions packages/fdc3-standard/src/api/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ export interface FDC3ChannelChangedEvent extends FDC3Event {
};
}

/**
* Type defining the format of event `contextCleared` objects
*/
export interface FDC3ContextClearedEvent extends FDC3Event {
readonly type: 'contextCleared';
readonly details: {
contextType: string | null;
};
}

/**
* Type defining valid type strings for Private Channel events.
*/
Expand Down
16 changes: 16 additions & 0 deletions website/docs/api/conformance/App-Channel-Tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,19 @@ hide_title: true
- `ACContextHistoryTyped`: Perform above test.
- `ACContextHistoryMultiple`: **B** Broadcasts multiple history items of both types. Ensure that only the last version of each type is received by **A**.
- `ACContextHistoryLast`: In step 5. **A** retrieves the _untyped_ current context of the channel via `const currentContext = await testChannel.getCurrentContext()`. Ensure that A receives only the very last broadcast context item _of any type_.


## Clearing Context

| App | Step | Details |
|-----|-------------------------|-----------------------------------------------------------------|
| A | 1. Retrieve `Channel` | Retrieve a `Channel` object representing an 'App' channel called `test-channel` using: <br />`const testChannel = await fdc3.getOrCreateChannel("test-channel")` |
| A | 2. Add Context Listener | Add an _typed_ context listener for `fdc3.instrument`, using: <br />`await testChannel.addContextListener("fdc3.instrument",handler)`|
| B | 3. Retrieve `Channel` | Retrieve a `Channel` object representing the same 'App' channel A did (`test-channel`)|
| B | 4. Broadcast | B broadcasts both an `fdc3.instrument` context and an `fdc3.contact` context, using: <br /> `testChannel.broadcast(<fdc3.instrument>)` <br /> `testChannel.broadcast(<fdc3.contact>)`|
| A | 5. Receive Context | An fdc3.instrument context is received by the handler added in step 2.<br />Ensure that the fdc3.instrument received by A is identical to that sent by B<br />Ensure that the fdc3.contact context is NOT received. |
| A | 6. Add Event Listener | Add an event listener for `contextCleared` event, using: <br />`await testChannel.addEventListener("contextCleared",handler)` |
| B | 7. Clear Context | B clears context using `testChannel.clearContext()`|

- `ACClearContext1`: Perform above test.
- `ACClearContext2`: Perform above test, but add specific type of the context type to the `testChannel.clearContext()`.
Loading
Loading