Coder Social home page Coder Social logo

api's Introduction

npm-build website-build GitHub release (latest by date) npm FINOS - Released GitHub Stack Overflow

FDC3

The mission of the Financial Desktop Connectivity and Collaboration Consortium (FDC3) is to develop specific protocols and taxonomies to advance the ability of desktop applications in financial workflows to interoperate in a plug-and-play fashion and without prior, bi-lateral agreements.

About this Repository

FDC3 is a standard. This repository houses the documentation and specifications for the ratified FDC3 standards.

Using the standard

Check out the documentation website for the different components of the standard, an overview of common use cases, developer API docs and standard compliance information.

Latest version of the standard is 1.1. See all available versions.

Learn more and interact with the Community

To learn more and ask questions you subscribe to the FDC3 General List by emailing [email protected]. Another great way to interact with the standard participants is to attend the quarterly FDC3 General meeting: you should receive an invite by signing up to the general list or you can find the meeting in the FINOS Project Meetings Calendar.

Using the standard? Let us know!

If you an existing individual or corporate user of the FDC3 standard, we would love to hear from you: just email the FDC3 General List with details about how you are using the standard. If you'd like to be listed as a standard user, you can directly send a pull request to update our website or, if listing your logo publicly requires legal evaluation, you can reach out privately to the FDC3 Product Management Committee.

Participate in the standard process

The FDC3 Standard Working Group meets monthly: you are welcome to join by subscribing to the FINOS Project Meetings Calendar. If you'd like to formally enroll as a voting standard participant process (as described in our standards governance) please email [email protected] making your intent to participate in the standard process explicit. Please note that standard participants are bound to the provisions in the FINOS IP Policy as described in the FINOS standards governance.

Contributing code to this repository

If you'd like to contribute code to this repository:

  1. Fork it (https://github.com/finos/FDC3/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

The team will review the PR and decide about merging.

Note that you will require a contributor agreement (individual or corporate) before your code can be merge, so please review FINOS Contribution requirements.

NOTE: Commits and pull requests to FINOS repositories will only be accepted from those contributors with an active, executed Individual Contributor License Agreement (ICLA) with FINOS OR who are covered under an existing and active Corporate Contribution License Agreement (CCLA) executed with FINOS. Commits from individuals not covered under an ICLA or CCLA will be flagged and blocked by the FINOS Cla-bot tool. Please note that some CCLAs require individuals/employees to be explicitly named on the CCLA.

Need an ICLA? Unsure if you are covered under an existing CCLA? Email [email protected]

Roadmap

With Productization on track to land at end of Q1, the expectation is that Q2 will be focused on implementations and feedback from those implementations driving further standards.

Target Items for Q2

API

  • Expand the broadcast API or introduce a new channels API to support the context setting use case.
  • Publish npm package with FDC3 API definitions.

App Directory

  • Search capabilities, surfacing other content
  • Manifest format detail (describing the content)
  • Eventing

Context Data

  • Pivot to JSON schema for representing type definitions. We have found that TypeScript is too implementation-specific and too restrictive in practice.
  • Use https://quicktype.io/ to generate type definitions from JSON schema for multi-language support.
  • Formalise current example types into official FDC3 types for contact, organisation, instrument etc in conjunction with/based on the Financial Objects program work.

Intents

  • Add detailed documentation to each intent - linking to use cases
  • Align closer with Context Data WG
  • Evaluate real use cases, given that we have input from early adapters
  • Extend with new intents, based on above + accepted use cases

Use Cases

  • Continue to process new and existing FDC3 Use Cases
  • Assess extending the use cases working group to additional FINOS programs

Backlog Beyond Q2

  • Define the next set of FDC3 Context Data types in conjunction with/based on Financial Objects working group work.
  • Work with Financial Objects and other FINOS programs to reach consensus on how to make standardized taxonomies available for consumption, both for viewing/editing and programmatically e.g. for validation.
  • Create comprehensive examples of use cases that show how to use the various FDC3 standards together to enable interoperability.
  • App Directory Identity and authentication

License

Copyright 2017 FDC3

Distributed under the Apache License, Version 2.0.

SPDX-License-Identifier: Apache-2.0

api's People

Contributors

colineberhardt avatar keshaldesai avatar maoo avatar rikoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

api's Issues

listener objects don't have a mechanism for unsubscribing

Both the IntentListener and ContextListener allow you to subscribe to events raised by the Desktop Agent. However, neither of them have a mechanism for removing this subscription.

Also, their relationships with the Desktop Agent is a little hidden, I'm guessing that they access some global agent instance in order to register themselves? This has a couple of issues:

  1. It relies on a singleton Desktop Agent
  2. The relationship between agent / listener isn't explicit - which can give rise to memory leaks.

I'd prefer to see a more explicit subscribe / unsubscribe:

For example:

const viewChartListener = fdc3.addIntentListener("ViewChart", (context) => {
  // do something meaningful here ...
  console.log("intent event occurred with context", context);
});

// .. at some point in the future ..
viewChartListener.unsubscribe();

Suggestion: Document the API via TypeScript

Currently the API is documented in pseudo-code, which means some important detail is missing, e.g. fdc3.open returns a Promise, but it doesn't document what the promise resolves to?

I'd like to propose that the interface is documented as a TypeScript type definition. This should will give a more formal API specification that people can implement.

Note: this does not mean that implementations of the API must use TypeScript - it just provides a convenient format for specifying / documenting the interface

What happens if an application is opened with context?

It is unclear to me from the API documentation what happens if an application is launched with the open(name: String, context: Context): Promise<void> function.

My assumption is that the context will be handled by the context listener (contextListener(handler: (context: Context) => void): Listener), but what does this mean? Is opening an app with a context the same as first calling open without a context, followed by broadcast with a context?

If this is the case, do we really need the context as part of opening an application? Isn't it more explicit and less ambiguous for an application to call broadcast if it wants to send some context to an application.

I would appreciate further insight as to when it would make sense to send an arbitrary payload to an application on startup when it is not in the context of a particular intent.

I guess I don't mind this functionality, but I think the intended usage should be made clear in the documentation.

Generated documentation in docs folder contain paths to contributors' forks

The README.md asks contributors to run yarn run doc after making changes, but this produces URI links ("Defined In") to their own forks.

This means that:

  • These files change for every PR by a different contributor, polluting code diffs.
  • These paths to forks get merged into the upstream repo still containing links to the fork, thereby making them incorrect.

These URI paths should either be relative, or always point to the upstream repo. If this is not possible, they should not be included at all, or generated documentation should not be checked in to the repo.

Example:
*Defined in [interface.ts:41](https://github.com/ColinEberhardt/API/blob/eac0696/src/interface.ts#L41)*

fix types for string and object

Currently, the TS interface uses "String" and "Object" as types. Should be "string" and "object" (actual types vs objects).

Rename listener methods

Currently we have the following:

intentListener(intent: String, handler: (context: Context) => void): Listener;
contextListener(handler: (context: Context) => void): Listener;

In keeping with web conventions (e.g. the DOM addEventListener method), and the standard approach of using 'verb phrases' for method names, I'd propose adding an add prefix to each:

addIntentListener(intent: String, handler: (context: Context) => void): Listener;
addContextListener(handler: (context: Context) => void): Listener;

Remove reliance on desktop agent being global

Currently all of the API methods are defined as properties of a global fdc3 object. This means that there can only ever be a single Desktop Agent within the current JS process. This might make sense now, but could be limiting in the future.

I'd suggest defining a non-global API, where methods are invoked on an Agent object. This object could be accessed via a global in the short-term, but would at least leave the door open for interacting with multiple agents.

For example this code:

fdc3.addIntentListener("ViewChart", console.log);

Would become:

const agent = fdc3.getAgent(); // obtain the current singleton
agent.addIntentListener("ViewChart", console.log);

This also makes it easier to mock / test the API.

Resolve by context only is required

A very important use case is resolving possible intents when you only have a context as a starting point.

const contact = {
  type: 'fdc3.contact',
  id: {
    email: '[email protected]'
  }
};

const results = await fdc3.resolve(contact);

This will return an array of applications + intents, e.g.

// * Call - Skype
// * Call - Zoom
// * Chat - Skype
// * Chat - Symphony

Now the source application can render a context menu or toolbar based on this information, or filter the results based on business logic. Once a user has selected an option, sendIntent can be used to invoke a particular intent:

fdc3.sendIntent(results[0].intent.name, contact, results[0].application.name)

This should be provided either by changing the existing resolve call to except either an intent or a context, like so:

interface IntentApplicationPair {
  intent: Intent;
  application: Application;
}

resolve(item: IntentName | Context): Array<IntentApplicationPair>

Or by having explicit operations for resolving intents and contexts (my preferred option), like so:

resolveIntent(intent: IntentName, context?: Context): Array<Application>
resolveContext(context: Context): Array<IntentApplicationPair>

Should name in fdc3.open be an AppIdentifier?

The comment for open(name: String, context: Context): Promise<void> says "Launches/links to an app by name".

Elsewhere (e.g. when sending an intent), type AppIdentifier = String is used. Is the "name" used in open the same as the app identifier used for intents? If it is the same, the same terminology should be used consistently.

If it is not the same, "name" needs to be explained in more detail to make the distinction clear. I would argue however that it should be the same app identifier used elsewhere if it is not, for the sake of API consistency.

In which case, it should probably be open(name: AppIdentifier, context: Context)

Add API usage examples

Either have an examples folder in the repo with code examples of using the API, or add example code to documentation comments.

Returning IntentResolution means an app needs to wait for a target app to finish handling an intent

The latest changes include a ResolutionObject returned by raising an intent.

This is very problematic for the fire-and-forget use case. In our current implementation, the intent resolver will find a target application to pass the intent on to and do that, but it then returns to the intent originator without any guarantees about whether the target app could be started, successfully received the intent, and finished handling the payload.

I think mandating a ResolutionObject forces all intents to wait for the target app to finish handling the intent payload, thereby removing the ability to do fire-and-forget.

This is why I wanted to the fire-and-forget and request-response API to be separated. I am not sure they can be handled with the same API.

Suggestion: Intents should not be stateful objects.

Currently intents are used as follows:

// how we locate the agent is platform specific - assuming it is a global in this example!
const agent = fdc3;

const context = {};
const intent = agent.intent("intent", context);

// at this point you can mutate the various properties
intent.target = "foo";

// when sending you can also change the context and target!
const result = await intent.send({foo: "bar"}, "MyApp")

// do something with the result
console.log(result);

// what state is the intent object in here? can I send again?

The above code snippet highlights quite a few ambiguities.

I'd propose a simpler API, that removes the Intent object altogether:

const agent = fdc3;

const context = {};
const intent = "DoSomething"
const result = await agent.sendIntent(intent, context);
console.log(result);

Much simpler!

fdc3.register how is the app name determined?

fdc3.register id documented as follows:

Dynamically registers an intent with the agent. Returns confirmation of the registration.

fdc3.register(intent: String)

However, the documentation for resolve indicates that an intent / context pair resolves to a list of app names.

When you register an intent via fdc3.register how is the app name determined?

Proposed removal of action ...

A subtle renaming to remove the concept of action ...

// an interface that relates intents to apps
interface AppIntents = {
  intent: IntentMetadata;
  apps: Array<AppMetadata>;
}

// an *** example *** context
const context = {
  person: "Bob Smith"
};

// I have a context object, and want to know what I can do with it, hence, I look
// for intents ...
const intents: AppIntents = await agent.findIntentsForContext(context);

// returns for example: 
// [{
//     intent: { name: "StartCall", displayName: "Call" },
//     apps: [{ name: "Skype" }]
// },
// {
//     intent: { name: "StartChat", displayName: "Chat" },
//     apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }]
// }];

// select a particular intent to raise 
const startChatIntent = intents[1];

// targeted at a particular app 
const selectedApp = startChatIntent.apps[0];

// raise an intent, passing the given context, to a specific app
await agent.raiseIntent(startChatIntent.intent.name, context, selectedApp.name);

Note raiseIntent signature should be updated to clarify (i.e. type) the third param.

Rename resolve method

The resolve method for the DesktopAgent interface is generically named. I propose that it be renamed to queryIntents, queryActions, findIntents, findActions, or something similar.

Resolve/findIntents: Falsy argument

The comments for resolve/findIntents states:

If intent argument is falsey, then all possible intents - and apps corresponding to the intents - are resolved for the provided context.

I would prefer if we are more explicit about the first argument than "falsy". It doesn't fit well into the TypeScript paradigm to accept multiple possible arguments with the same semantics.

I propose that we standardise on null and/or undefined. Thinking about it, undefined is probably better.

This would make the type definition:
resolve(intent: String | undefined, context?: Context): Promise<Array<ActionMetadata>>;
which is nice and explicit - either a string, or undefined.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.