The future of SDKs for the web platform

Pawel Uchida-Psztyc
RAML by Example
Published in
5 min readNov 21, 2018

Recently, at Chrome Dev Summit, Gray Norton was talking about a new proposal for the web platform (a set of specifications for how browsers render web pages): Layered APIs. It was a great talk about how we can standardise high level APIs using ES6 modules. At the end of the talk Gray asked if anyone had an idea for new primitives or modules for the web. I am answering that call.

At MuleSoft, I create tools to make REST API development easier for developers. I’ve spent the last 3 years creating a set of web components dedicated to API documentation and testing. Another area that interest me is SDKs. The current state of play is that the REST API owner has to produce the documentation for that API and the SDKs for each targeted platform. At Mulesoft, we responded to the first need by creating API Console, a web component which generates documentation for an API. As long as you model your API using RAML or OAS, you can use it to create an API portal or embed the documentation to existing website. As for SDKs, there are tools that generate bundles for different platforms using API spec files. But still, the owner of the API has to publish and document the SDK. I’d like to change this state because I think it is inefficient and because we, as a community, can do better.

What if the browser was able to understand an API and auto-generate the web SDK for a website? In this world all SDKs generated by the browser have unified interface so a web developer has to learn how to use the web SDK once and then only the API structure using API documentation tool. To do this, 3 things would have to happen. First the browser has to get the API definition. We can use the existing <link> element for that.

<link rel="api" type="RAML 1.0" href="api.raml" title="my-api">

I’m proposing a new value for the “rel” attribute: api. It means that the external resource is an API model and should be read as such. The “type” attribute refers to the API definition format. It can be RAML or OAS. Finally “title” would be used to reference the API in the JavaScript interface.

Second thing to do is to parse the API. MuleSoft developed an open source AML (Anything Modeling Language) and AMF (AML Modeling Framework). It provides a common programming interface that lets developers interact with any API specification. AMF can be used to generate a common API model from every API native format.

Finally the browser would generate a JavaScript interface for the API based on the information read from the referenced spec and cache the result locally so next time it skips the downloading and parsing process (that is a very high level description of this part).

API parsing and generating can take some time so the operation has to be asynchronous.

<script>
await navigator.sdk.ready();
const sdk = await navigator.sdk.api('my-api');
const response = await sdk.api.profile.me.get();
const profile = await response.json();
</script>

The first step is to ensure that all referenced APIs in the head section has been downloaded by the browser. The second step is to parse a specific API and return a reference to the generated SDK. The SDK reflects the structure of the API. It contains the authentication methods, the model definitions, and the structure. For example, the api.profile.me.get() performs a GET request to /profile/me endpoint.

Functions that calls an endpoint can accept the init argument which is the same as the Request object of the Fetch API.

<script>
const init = {
headers: {'x-api-key': '....'},
body: JSON.stringify({
...
});
};
const response = await sdk.api.todos.post(init);
</script>

To validate user input against the API specification, we could use the validation property of the sdk object.

<script>
const init = {
headers: {'x-api-key': '....'},
body: JSON.stringify({
...
});
};
const validationResult = sdk.validation.todos.post(init);
console.log(validationResult.valid);
console.log(validationResult.messages);
</script>

Most of APIs requires some form of Authentication. This is modeled in the API specification. The browser would fail the request when the user is not Authenticated. The WebSDK also exposes the interface to perform authentication.

<script>
const config = {
type: 'OAuth 2.0',
grantType: 'implicit',
interactive: true,
clientId: '....',
redirectUri: '...'
};
if (!sdk.auth.isAuthenticated(config)) {
await sdk.auth.authenticate(config);
}
</script>

The isAuthenticated() function checks if the user is authenticated for a given configuration. The configuration structure depends on the authentication type. It requires providing configuration options for the authentication type and node defined in the API definition. Finally it allows to authenticate() the user by performing actions like rendering an auth popup or username/password dialog.

So far this was a brief description of the proposal for a web primitive. It gives a low level API so frameworks and developers can build on top of it. However with the “layered APIs” spec we could do better. Imagine declarative API calls using HTML, e.g.:

<script type="module" src="std:web-sdk"></script>
<script type="module" src="std:web-sdk-authentication"></script>
<script type="module" src="std:web-sdk-request"></script>
<web-sdk api="my-api" id="api">
<web-sdk-authentication client-id="..." redirect-url="..." id="auth"></web-sdk-authentication>
<web-sdk-request endpoint="/users/me" method="GET" id="profile"></web-sdk-request>
</web-sdk>
<script type="module">
api.addEventListener('ready', () => {
if (!auth.isAuthenticated()) {
auth.authenticate();
}
});
auth.addEventListener('authenticated-changed', (e) => {
console.log('User authenticated: ', e.target.authenticated);
});
profile.addEventListener('api-response', (e) => {
e.target.response.json()
.then((profile) => console.log(profile));
});
</script>

This would import 3 standard modules required for the web API to work: “web-sdk” would be the framework, “web-sdk-authentication” would manage user sessions and “web-sdk-request” would perform API calls. The framework takes care of downloading and parsing the API spec file. Once it is ready, all APIs are available to use. When the user is authenticated, or when the endpoint does not require authorization, the “web-sdk-request” module issues the request to the server. The application listens for an event that indicates the response is ready. The event is dispatched once the API call ends.

This is just a beginning of a web API proposal to the web platform spec. I hope we will be able to start the discussion with Chrome, Firefox, Edge and Safari teams on this proposal. This would change the way we consume APIs in the web platform.

Please leave a comment or feel free to contact me if you are interested in standardizing this API. Meanwhile check the project page for polyfills and technical description: https://github.com/advanced-rest-client/web-sdk

--

--

Pawel Uchida-Psztyc
RAML by Example

Design, APIs, front-end, strategy, product, and educator. I work for big tech but I share my personal views and opinions.