npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@logilab/cwclientlibjs

v1.3.1

Published

client library for CubicWeb's rqlcontroller API

Downloads

503

Readme

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.

If you want to communicate with the API Cube, use cubicwebjs instead.

To read about the rql client, go to Section Client.ts. To read about the providers, go to Section Providers.ts.

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. The CSRF token will be included if allowsCrossOrigin is false (the default).

import {providers, client} from '@logilab/cwclientlibjs';

// url is the base url of your cubicweb instance
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); // [[123,1], [234, 2]]
});

rqlClient.queryBindings(query).then(res => {
    console.log(res); // [{'X': 123, 'Y': 1}, {'X':234, 'Y':2}]
});

rqlClient.queryAndTransform(query, 'rdf').then(res => {
    console.log(res); // equivalent to http://my-cubicweb-instance-base-url/view?rql=Any X, Y WHERE X is BlogEntry, X entry_of Y &vid=rdf
});

rqlClient.transactionV1([query]).then(res => {
    console.log(res); // [[[123,1], [234, 2]]]
});

rqlClient.transactionV2([query]).then(res => {
    console.log(res); // [{rows: [[123,1], [234, 2]], variables : ['X','Y']}]
});

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';

// url is the base url of your cubicweb instance
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); // [[123,1], [234, 2]]
});

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';

// url is the base url of your cubicweb instance
const url = 'http://my-cubicweb-instance-base-url/';

const rqlClient = new client.CwRqlClient(new client.CwSimpleHttpClient(url));

// Schema will not be cached
const schemaProvider = new providers.RqlEntitySchemaProvider(rqlClient);

// Schema will be cached
const schemaProviderWithLocalStorage = new providers.RqlEntitySchemaProvider(
    rqlClient,
    'mySchemaStorageKey'
);

// load a schema
schemaProvider.load().then((schema: providers.Schema) => {
    console.log(schema);
});

// load a 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';

// url is the base url of your cubicweb instance
const url = 'http://my-cubicweb-instance-base-url/';

const rqlClient = new client.CwRqlClient(new client.CwSimpleHttpClient(url));

// Schema will not be cached
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

The tests relies on an instance with the test-server cube to run.

The Dockerfile located in test-server creates an image with an instance ready for use. Building it is as simple as:

docker build -t cw-test-server .

You can then run the instance using docker run:

docker run -p 8080:8080 cw-test-server

Once the instance is running, launch the tests:

npm run test

By default the test instance is running on "http://localhost:8080". If you need to start it on a different host/port, use the CW_BASE_URL environment variable.

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.