Security News
Maven Central Adds Sigstore Signature Validation
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
@jbouduin/hal-rest-client
Advanced tools
The hal-rest-client library helps you to work with Hypertext Application Language (HAL) in Typescript.
This is a friendly fork of the original hal-rest-client repository. Reason for doing this: the original repository has been archived and is showing some severe vulnerabilities.
any
and object
whenever possibleI am willing to merge any useful Pull Request (feel free to create them), if:
Using npm :
npm install @jbouduin/hal-rest-client
The library provide two access method :
HalResource
to map service returnmodel
HalResource
To have access to your service, you need to create a hal-rest-client instance.
import { createClient } from "hal-rest-client";
const client = createClient();
// or
const client = createClient("http://exemple.com/api");
To get a resource, you can use fetchResource method.
const resource = await client.fetchResource("http://exemple.com/api/resources/5")
or
const resource = await client.fetchResource("/resources/5");
fetchResource return a promise. you can use
then
andcatch
to get result. you can get resource property, embedded property or link usingprop
method.
const name = resource.prop("name");
const resourceURI = resource.uri;
for a link, on link
service return
const link = resource.prop("link_name");
// or
const link = resource.link("link_name");
link attribute type is
HalResource
Links are made to be followed. So you can simply fetch a link using fetch
method.
const link = resource.link("link_name");
await link.fetch();
const name = link.prop("name");
Note that link()
returns an empty HalResource
with its uri
set. You need to call fetch()
to populate the HalResource.
The library also supports arrays of links using Array syntax:
const link = resource.link("link_name")[0];
await link.fetch();
const name = link.prop("name");
If you link is templated, you can set parameter to fetch to compute fetch URL.
// link "link_name" is a templated link like this
// /bookings{?projection}
const link = resource.link("link_name");
const bookings = await link.fetch(); // fetch /bookings
const bookingsWithName = await link.fetch({projection : "name"}); // fetch /bookings?projection=name
// link "link_infos" is like this
// /infos{/path*}
const link = resource.link("link_infos");
const infos = await link.fetch(); // fetch /infos
const infosForFoo = await link.fetch({path: "foo"});
Note that named links are synonymous with props:
const link = resource.link("link_name");
const prop = resource.prop("link_name");
link === prop // true
This means you can navigate a HAL hierarchy (referencing and fetching) using props alone:
// using .prop()
const foo = await resource.prop("foo").fetch();
const bar = await foo.prop("bar").fetch();
// using .links
bar.props === resource.links.foo.links.bar.props // true
Resource can be updated, and saves with a PATCH query.
resource.prop("name", "new value");
await resource.update()
update return a promise. use
await
to wait end of update.
To set a link, you can use prop
or link
function. the new value for a link must be an HalResource
populated or not.
// init an HalResource called newResource
resource.prop("link_name", newResource);
await resource.update();
on the request send to server, only the uri is sent not all the object.
To create a resource, you must use method create
on your client.
await client.create("/resources", { name: "Thomas" });
If your server return the new created object as body, you can do this :
const resource = await client.create("/resources", { name: "Thomas" });
Resource is an HalResource if server return a resource or just json if a simple json is returned
hal-rest-client can use model class to fetch HAL rest result. Model class is a definition of service return.
for this exemple, we create a Resource model.
import { HalProperty, HalResource } from "hal-rest-client";
import { Person } from './person.model';
class Resource extends HalResource {
@HalProperty()
public name;
// for array, you must(!) specify the resource type
@HalProperty({ resourceType: Resource})
public subResources: Array<Resource>;
// if name on hal-service is not the same as the attribute name
// you can add the hal-service property name as parameter
@HalProperty({ name: "main-owner"})
public owner: Person;
}
your model musT extends IHalResource
each property must be annoted with
@HalProperty
. _links, _embedded, an simple props must to be map with@HalProperty
To read an object, you need to create a client, and call fetch
method.
import { createClient } from "hal-rest-client";
const client = createClient();
// or
const client = createClient("http://exemple.com/api");
call fetch method
import { Resource } "./resource.model";
const resource = await client.fetch("/resource/5", Resource);
fetch return a promise. you can use
then
andcatch
to get result. Otherwise you can useawait
see this article
Read props is simply call object attributes.
const name = resource.name;
const uri = resource.uri;
links are made to be followed. So you can simply fetch a link using fetch
method.
await resource.owner.fetch();
const ownerName = resource.owner.name;
mapped links return an empty
HalResource
, justuri
is setted. Callfetch
populate the HalResource.if ower is not a link but an embedded resource, you don't need to call
fetch
. Object is populate with embedded resource
fetch return the fetched object, so you can do that :
const resourceOwner = await resource.owner.fetch();
const ownerName = resourceOwner.name;
you can fetch a templated link like this
// link "booking" is a templated link like this
// /bookings{?projection}
const bookings = await resource.booking.fetch(); // fetch /bookings
const bookingsWithName = await resource.booking.fetch({projection : "name"}); // fetch /bookings?projection=name
// link "infos" is like this
// /infos{/path*}
const infos = await resource.infos.fetch(); // fetch /infos
const infosForFoo = await resource.infos.fetch({path: "foo"});
Resource can be updated, and saved with a PATCH query.
resource.name = "new value";
await resource.update()
update returns a promise. use
await
to wait end of update.
You can set a link, the new value for a link must be a HalResource
or an other model, populated or not.
// init an HalResource called newPerson
resource.owner = newPerson
await resource.update();
when sending the request send to server, only the uri is sent, not the object complete object.
To create a resource, you have two choices :
create
method on clientcreate
method on this objectTo create a resource, you must use method create
on your client.
await client.create("/resources", { name: "Thomas" });
If your server returns the newly created object as body, you can do this :
const resource = await client.create("/resources", { name: "Thomas" }, Resource);
Resource is a Resource object if server return a resource or just json if a simple json is returned
To create a resource object, you must use createResource
method
import { createResource } from "hal-rest-client";
const resource = createResource(client, "/resources", Resource);
After resource creation, set properties
resource.name = "my resource";
resource.owner = owner;
Call create
method
const createdResource = await resource.create();
if your server returns a newly created object, create return this object. createdResource is of type Resource. Create doesn't populate the existing object.
You can configure some parameter on you client. HalClient use axios to run ajax request.
You can configure each parameter describe here
To do, you have two solutions:
// example to configure CORS withCredentials parameter
createClient('http://test.fr', {withCredentials : true})
// or
client.config.withCredentials = true
You can configure interceptors, you have two interceptor types :
// Add a request interceptor
halClient.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
halClient.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Two parameters can be used for create a client.
a base URL can be used to fetch resources.
import { createClient } from 'hal-rest-client';
const client = await createClient('http://foo.bar');
header can be set to HalRestClient
const client = await createClient('http://foo.bar', {'headers' : {'authorization': 'Basic Auth'}});
// or
const client = createClient('http://foo.bar');
client.addHeader('authorization', 'Basic Auth');
When the client fetch a resource, a parser is used to convert json on HalResource. You can customize the parsing method. To do this, you need extends JSONParser and implements your own jsonToResource method. After, you can set the parser like this.
client.setJsonParser(myParser);
HalProperty
annotation is used to map model with service body.
HalProperty have two parameters:
@HalProperty("property-name")
@HalProperty(Type)
@HalProperty("property-name", Type)
Fetch a service, and return an HalResource. Parameter is the URI.
client.fetchResource('/resources/5');
// or
client.fetchResource('http://test.fr/resources/5');
Fetch a service and return a model class. Parameter is the URI and model class.
client.fetch('/resources/5', Resource);
// or
client.fetch('http://test.fr/resources/5', Resource);
Fetch an array service. Return an array of object (HalResource or model class). The service can return :
client.fetchArray('/resources', Resource);
// or
client.fetchArray('http://test.fr/resources', Resource);
// or
client.fetchArray('http://test.fr/resources', HalResource);
To create or update resource, Typescript Objects are serialized on simple json to send at server.
on create
or update
method you can use custom JsonSerializer.
const result = await resource.update({
parseProp : (value) => "serializer." + value,
parseResource : (value) => "serializer2." + value.uri,
});
FAQs
Hal rest client for typescript
The npm package @jbouduin/hal-rest-client receives a total of 0 weekly downloads. As such, @jbouduin/hal-rest-client popularity was classified as not popular.
We found that @jbouduin/hal-rest-client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.