cwclientlibjs - client library for CubicWeb's rqlcontroller
Javascript clone of the cwclientlib python library that wraps the rqlcontroller
API offered by the cubicweb-rqlcontroller cube.
To read about the rql client, go to Section Client.ts. To read
about the providers, go to Section Providers.ts.
For internal use : sonarqube analysis
Client.ts
The client namespace provides helpers to run RQL queries on a
cubicweb instance with the rqlcontroller cube.
The class CwRqlClient implements the interface
RqlClient and provides the following functions:
- queryRows(query:string, params?:any): runs query on the cubicweb
instance and returns the results as RqlRows in a
Promise. This function calls transactionV1
- queryBindings(query:string, params?): runs query on the cubicweb
instance with and returns the results as RqlSolutions
in a Promise. This function calls transactionV2
- queryAndTransform(query:string, params?,viewId): Build the url
corresponding to the query with a given viewId and returns the content in a
Promise
- transactionV1(queries): runs a set of queries with the rqlio/1.0
interface and returns the query results or throws an error if something went
wrong
- transactionV2(queries): runs a set of queries with the rqlio/2.0
interface and returns the query results as
RqlIoV2TransactionResponse
A RqlClient relies on an HttpClient. Two implementations are available
CwSimpleHttpClient and
CwSigningHttpClient.
CwSimpleHttpClient: anonymous request
CwSimpleHttpClient requires a baseUrl (the base url of a
cubicweb instance). A boolean can be added to allow cross origin requests. The
CwSimpleHttpClient can perform a doLogin(login,password) operation on the
cubicweb instance and perform the queries by using cookies (see Known
issues). It can also be transformed into a CwSigningHttpClient
(toSigningClient()) after a doLogin() operation. It requires that the CubicWeb
user has at least an enabled token linked to his/her account.
import {providers, client} from '@logilab/cwclientlibjs';
const url = 'http://my-cubicweb-instance-base-url/';
const rqlClient = new client.CwRqlClient(
new client.CwSimpleHttpClient(url, true)
);
const query = 'Any X, Y WHERE X is BlogEntry, X entry_of Y';
rqlClient.queryRows(query).then(res => {
console.log(res);
});
rqlClient.queryBindings(query).then(res => {
console.log(res);
});
rqlClient.queryAndTransform(query, 'rdf').then(res => {
console.log(res);
});
rqlClient.transactionV1([query]).then(res => {
console.log(res);
});
rqlClient.transactionV2([query]).then(res => {
console.log(res);
});
CwSigningHttpClient: authenticated requests.
CwSigningHttpClient requires a baseUrl (the base url of a
cubicweb instance), a tokenName, a tokenValue and a hashMethod code. Each
request will contain an Authorization header with the connection token and its
hashed value.
These tokens are managed on your CubicWeb instance under Profile > Actions > Add
Authentication Token.
import {providers, client} from '@logilab/cwclientlibjs';
const url = 'http://my-cubicweb-instance-base-url/';
const rqlClient = new client.CwRqlClient(
new client.CwSimpleHttpClient(url, "my-token-name", "1a2b3c4d5e6f...")
);
const query = 'Any X, Y WHERE X is BlogEntry, X entry_of Y';
rqlClient.queryRows(query).then(res => {
console.log(res);
});
Providers.ts
The provider namespace provides two main objects:
EntitySchemaProvider and
EntityProvider.
EntitySchemaProvider
A RqlEntitySchemaProvider provides an interface to load
a CubicWeb instance Schema.
A EntitySchemaProvider provides the following functions:
- getAllRelationsFor(typeEid:number): Outputs two lists: relationsFrom and
relationsTo relative to the CWEType referenced by typeEid
- getEntitySchemaByName(typeName: string): Retrieves a CWEType (as
EntitySchema) from its name
- getEntitySchemaById(typeEid: number) : Retrieves a CWEType (as
EntitySchema) from its eid
- getEntitySchemaFor(eid:number) : Retrieves a CWEType (as EntitySchema)
for a given instance number
- load(): Loads the Schema
An RqlEntitySchemaProvider can instantiate a
LocalStorageEntitySchemasLoader which will store the
schema in the browser's window.localStorage, if given a 'storageKey' value.
Additionnaly, two functions: isCacheUsable and onRetrieved can be given
to the RqlEntitySchemaProvider, they can be used to deal with schema versioning.
- isCacheUsable is called in a LocalStorageEntitySchemasLoader, it takes a
providers.Schema
as input and outputs a boolean Promise. If the promise is
resolved with the value true
, the schema will be loaded from the
localStorage. Otherwise, if will be queried and loaded from the cubicweb
instance again. - onRetrieved is called after the schema has been queried and loaded from
the cubicweb instance.
If no 'storageKey' value is given, a
RqlEntitySchemasLoader will be instantiated and the
schema will be queried at every call of the load
function.
import {providers, client} from '@logilab/cwclientlibjs';
const url = 'http://my-cubicweb-instance-base-url/';
const rqlClient = new client.CwRqlClient(new client.CwSimpleHttpClient(url));
const schemaProvider = new providers.RqlEntitySchemaProvider(rqlClient);
const schemaProviderWithLocalStorage = new providers.RqlEntitySchemaProvider(
rqlClient,
'mySchemaStorageKey'
);
schemaProvider.load().then((schema: providers.Schema) => {
console.log(schema);
});
schemaProviderWithLocalStorage.load().then((schema: providers.Schema) => {
console.log(schema);
});
A Schema is a json object with two entries:
- a metadata object which is computed on the schema load. At the moment,
the metadata contains the schema loading timestamp.
- entities: a list of EntitySchema, each EntitySchema describes a CWEType,
its attributes and to and from relations.
Example instanciation of a schema object:
{
"metadata": {
"timestamp": "2020-04-20T09:35:49.183Z"
},
"entities": [
{
"eid": 30,
"name": "BlogEntry",
"modificationDate": "2009/09/01 12:15:04",
"specializes": null,
"attributes": [
{"eid": 78, "name": "title", "type": "String", "cardinality": 2}
],
"relationsTo": [
{
"eid": 6055,
"name": "entry_of",
"from": 30,
"fromName": "BlogEntry",
"fromCardinality": 1,
"to": 6044,
"toName": "Blog",
"toCardinality": 1,
"description": ""
}
],
"relationsFrom": [
{
"eid": 711,
"name": "tags",
"from": 61,
"fromName": "Tag",
"fromCardinality": 1,
"to": 30,
"toName": "BlogEntry",
"toCardinality": 1,
"description": "indicates that an entity is classified by a given tag"
}
]
}
]
}
EntityProvider
Three entity Providers:
- RqlEntityProvider: Provides access to entities
through a RQL enpoint. An EntitySchemaProvider can be specified on
implementation, for example to cache the Schema in the localStorage.
- EJsonExportEntityProvider: Provides access to
entities through the ejsonexport view of a RQL endpoint
- CachedEntityProvider: Caches the access to entities
provided by another provider
Each EntityProvider provides the following functions:
- getEntity(eid:number): Gets an entity given its eid
- getEntityGivenSchema(eid:number, entitySchema: EntitySchema): Gets an
entity given its expected entitySchema (CWEType, list of attributes,
relations to and from)
- getEntityTitleGivenSchema(eid: number, entitySchema EntitySchema) : Gets
the title for an entity, i.e., the value of the first attribute in the list
of the entitySchema attributes.
import {providers, client} from '@logilab/cwclientlibjs';
const url = 'http://my-cubicweb-instance-base-url/';
const rqlClient = new client.CwRqlClient(new client.CwSimpleHttpClient(url));
const schemaProvider = new providers.RqlEntitySchemaProvider(
rqlClient,
'storageKey'
);
const rqlEntityProvider = new providers.RqlEntityProvider(
rqlClient,
schemaProvider
);
const eJsonEntityProvider = new providers.EJsonExportEntityProvider(rqlClient);
const cachedEntityProvider = new providers.CachedEntityProvider(
rqlEntityProvider
);
cachedEntityProvider.getEntity(123456).then(entity => {
console.log(entity);
});
An entity will be a json object, whose keys are defined by its EntitySchema
(CWEType)
{
"@eid": 123456,
"@type": "BlogEntry",
"title": "Super Blog Post",
"entry_of_BlogEntry_Blog": [11111],
"tags_Tag_BlogEntry": [765432, 99999],
"modification_date": "2010/03/01 18:45:52"
}
Tests
Running the test suite requires nodejs, mocha and xhr2.
Known issues
There seems to be a problem with Cookie handling: in the doRequestFetch
function. The headers of the request seem to be empty for
every response. Therefore, the login functionality is broken for the moment as
it requires to access the Set-Cookie
fields of HTTP Responses.