Ketting 7 released
We just released version 7 of Ketting. Ketting is a generic HATEOAS client for Javascript.
A whole bunch of features have been added since September. We’ve been testing Ketting 7 in beta since January, so I’m excited to get this out the door.
I’ve been working on this project since 2016. Normally, I would expect a project like this to get a little stale. For me personally, the opposite has been true and using Ketting (especially with React) is starting to feel a bit like a paradigm shift.
Read on to see what’s new!
What is Ketting?
In short: Ketting is a generic REST client for Javascript. You can use it for pushing JSON objects via HTTP, but the richer your API is in terms of best practices and standard formats, the more it can automatically do for you.
It has support for Hypermedia formats such as HAL, Siren, Collection+JSON, JSON:API and can even understand and follow links from HTML.
In the past it was not uncommon to hear that HATEOAS is lacking a good generic client. If you are a Javascript/Typescript user this is no longer true.
More information can be found on the Github page.
What’s new?
Better HAL-Forms support
HAL-Forms is an extension of HAL, and adds support for ‘actions’ or
‘forms’, similar to what the <form>
tag is to HTML.
Since the start of the year HAL-Forms has seen major updates, which was a collaborative effort by several people from projects in the HAL community (including Spring HATEOAS and yours truly) and lead by it’s author Mike Amudsen.
Spring HATEOAS released its HAL-Forms updates in version 1.3 M2 (unclear if this is a stable release or not), and Ketting follows today.
Major new features in HAL-Forms include:
- Support for lookups
- Example use-case is rendering dropdowns/comboboxes.
- The list of possible options can either be provided in-line or via an external resource.
- JSON and
text/csv
is support for external resources.
- Support for most of the HTML5 input types, such as
checkbox
,color
,tel
,email
,textarea
, etc. - Support for many of the field attributes that also exist in HTML5 form
fields, such as
placeholder
,min
,max
,step
,cols
,rows
, and others. - Support for a form
target
. Previously this could also be supplied via the URI. - Support for multiple forms per document.
React bindings: <RequireLogin>
(note: all of the new react-ketting features were backported to Ketting 6)
react-ketting now has a RequireLogin
component, that can be use to handle
the OAuth2 authorization_code
flow in React applications.
Example usage:
function MyApp() {
return <RequireLogin
clientId="my-oauth2-client-id"
authorizeEndpoint="https://..."
tokenEndpoint="https://..">
You are now logged in!
</RequireLogin>;
}
React-bindings: useCollection
A useCollection
hook was added to easily render a collection on a server.
Example usage:
import { useCollection, useResource } from 'react-ketting';
import { Resource } from 'resource';
type Article = {
title: string;
body: string;
}
function ArticleList() {
const { loading, items } = useCollection<Article>('/articles');
if (loading) return <div>Loading...</div>;
return <section>
<h1>Articles!</h1>
{items.map( item => <ArticleItem key={item.uri} resource={item} /> ) }
</section>;
}
function ArticleItem({resource}: { resource: Resource<Article> }) {
const { loading, data } = useResource(resource);
if (loading) return <div>Loading...</div>;
return <div>
<h2>{data.title}</h2>
<p>{data.body}
</div>
}
React-bindings: refreshOnStale
Both useResource
and useCollection
got a refreshOnStale
flag, that will
cause Ketting to automatically ask the server for a new resource state if the
cache is marked stale for a resource.
This can have a pretty magical effect when you (for example) use a POST
request on a collection to add a new member.
If you also used a useCollection
hook on the same page to show the
collection, that collection will automatically refresh it’s own list.
The first fetch of useCollection
will include a Prefer-Transclude
HTTP
header, telling the user to (ideally) embed every item of the collection in
the response, but subsequent refreshes will not.
This means the first time we only need 1 HTTP request, but for refreshes only the collection itself (and not it’s members) need to be returned.
If your ‘create’ operation also returned Content-Location
, you can remove
one more HTTP request from that list.
Similarly this can be used for DELETE
requests of members of the collection,
as long as your response includes Link: </parent-collection>; rel="invalidates"
,
the collection will also automatically re-render with the deleted item removed.
For one application we took this a step further, and used Websockets to emit ‘stale’ events from the server. With virtually no modifications to the frontend, we were able to turn a single-user web application into an application that could reflect changes in real-time from other users who were using the application at the same time. This really felt like an emerging property of a well designed system (standing on the shoulders of decades of Hypermedia, HTTP and REST research).
Personally I’m very hyped about this feature, and I can’t wait to demo this on a meetups or a conferences (if my talk proposals ever get accepted!?).
Deprecation warnings
Ketting 7 will now emit warnings when it encounters a Deprecation
or Sunset
header, or when a link contains the status: "deprecated"
hint.
For more information about this feature, read my previous article about this feature.
Removed support for Prefer-Push
HTTP/2 Push support in browsers is effectively dead. To reduce drag,
I’ve removed the Prefer-Push
feature from Ketting.
Smarter caching of newly created resoures.
If you use Ketting to create a new resource (for example with POST
), and
the server returns a Content-Location
header in its response, it will
store the response body with the new URI in it’s cache.
This can potentially reduce roundtrips. Content-Location
is a way for a
server to say: ‘The response body is the representation of the resource
this URI’.
This is another great example of a HTTP caching feature in Ketting that goes beyond what Web Browsers typically do.
Other examples of this is being able to tease apart transcluded/embedded
responses, allowing servers to invalidate caches for entries with an
invalidates
link and exposing cache-related events to the user.
State
objects now have a .follow()
and .followAll()
function.
A State
object is returned when you (for example) call resource.get()
,
resource.patch()
, etc.
This object represents an ‘Entity’ or ‘State’ returned from the server, which really is a fancy way of saying ‘the body’ + headers that directly pertain to the body.
It also provides direct access to hypermedia features such as links and actions. The new addition lets you follow hypermedia links straight from any HTTP response.
const response = await myResource.post({
data: {
param1: 'value1'
}
});
// If response contained a HAL, Siren, HTML link or HTTP Link header,
// we can follow it!
const newResource = response.follow('more-info');
Upgrading
Upgrading should be relatively pain-free for most users, except if you extend Ketting with custom format parsers.
If you run:
npm i ketting@7
npm i react-ketting@2 # React users only
And typescript doesn’t complain, chances are that everything will work just as before.
Ketting 7 has been in development and used by us in production since January.
Future plans
Long-term Ketting plans include
- Better documentation and educational resources.
- More React support, including a library of components for automatically rendering Hypermedia Forms/Actions and automatic paging of collections.
- Bindings to other frontend-frameworks.
- An official Websocket add-on, to enable real-time multiuser collaboration and bi-direction state updates.