gbv / cocoda-sdk

SDK for Cocoda and coli-conc services
https://gbv.github.io/cocoda-sdk/
MIT License
5 stars 1 forks source link
cocoda coli-conc jskos ts4nfdi

Cocoda SDK

Test and build GitHub package version NPM package name standard-readme compliant

SDK for Cocoda and coli-conc services

Table of Contents

Install

npm i cocoda-sdk

We are also providing a browser bundle: https://cdn.jsdelivr.net/npm/cocoda-sdk@2/dist/cocoda-sdk.js (~51K gzipped, ~155K not gzipped) It will be available under the global name CDK and contain the listed members below (in particular the default instance CDK.cdk).

Usage

Import

cocoda-sdk exports a default instance, so the same object is used on each import of cocoda-sdk. We recommend using this instance over creating one's own.

const { cdk } = require("cocoda-sdk") // CommonJS
import { cdk } from "cocoda-sdk" // ESM

Since cocoda-sdk is an ES module, we'll use the import/export syntax in the rest of the documentation.

cocoda-sdk also exports some other members:

v1 Compatibility

cocoda-sdk v2 changed how it is exported and therefore it needs to be included differently.

// CommonJS
// Previously: const cdk = require("cocoda-sdk")
// Now:
const { cdk } = require("cocoda-sdk")
// or: const cdk = require("cocoda-sdk").cdk
// ES6
// Previously: import * as cdk from "cocoda-sdk"
// Now:
import { cdk } from "cocoda-sdk"
// Browser
// Previously the default instance was globally available under `cdk`.
// Now the module is available under `CDK` with `cdk` as one of its members. To easily make previous code compatible:
const { cdk } = CDK

Configuration

cocoda-sdk can be configured after import:

import { cdk } from "cocoda-sdk"
cdk.setConfig(config)

The configuration can also be loaded from a URL:

import { cdk } from "cocoda-sdk"
await cdk.loadConfig("https://raw.githubusercontent.com/gbv/cocoda/dev/config/cocoda.default.json")

The configuration is a JSON object corresponding the the configuration format of Cocoda. In particular, the configuration contains an array property registries.

If you only use cocoda-sdk with a single registry, configuration might not be necessary (see below).

Registries

A registry is an individual source of data, for instance a set of concept schemes available from a specific terminology service. The simplest registry consists only of a unique identifier (uri) and the name of the access provider (provider):

{
  "uri": "http://coli-conc.gbv.de/registry/local-mappings",
  "provider": "LocalMappings"
}

A list of available providers can be found below. Most providers need additional properties to work correctly.

Endpoint Determination

For many providers, you need to specify one or more endpoints on the registry object for it to work. There are, however, three steps in which these endpoints are determined:

  1. By explicitly specifying an endpoint on the registry object.
  2. By performaning a request to the provider's /status endpoint and parsing its result (which is done in registry.init()).
  3. By implication using the api base URL.

Values set earlier in these steps will never be overwritten by later steps. That means to disable an endpoint explicitly, you can set it to null when configuring the registry. Also, if step 2 is successful, it will be assumed that no further endpoints exist and all missing endpoints will be set to null, i.e. essentially skipping step 3.

Using a Single Registry

If you only have a single registry you want to access, you can initialize it as follows:

import { cdk, LocalMappingsProvider } from "cocoda-sdk"
// Local mappings are not included by default
cdk.addProvider(LocalMappingsProvider)
const registry = cdk.initializeRegistry({
  uri: "http://coli-conc.gbv.de/registry/local-mappings",
  provider: "LocalMappings"
})
// Now, access methods are available on the registry:
registry.getMappings()

Using Registries From a Configuration

If you initialize cocoda-sdk with a configuration, it will initialize all included registries automatically. Those registries are then accessible via cdk.config.registries. Alternatively, you can retrieve registries by URI:

// After setting up cdk
const registry = cdk.getRegistryForUri("...")

Providers

Providers allow access to different types of APIs.

The following providers are offered in cocoda-sdk by default:

The following providers are also exported, but have to be added via cdk.addProvider:

To add a provider, append Provider to its name and import it together with cdk:

import { cdk, LocApiProvider } from "cocoda-sdk"
cdk.addProvider(LocApiProvider)

Note that in the browser bundle, all providers listed above are included and do not have to be added separately.

Please refer to each provider's documentation for how exactly to configure that provider: Documentation

It is also possible to add custom providers that inherit from BaseProvider:

import CustomProvider from "./custom-provider.js"
cdk.addProvider(CustomProvider)

It is then possible to use that provider via cocoda-sdk as well. (See also: Example under examples/custom-provider.js.)

Multiple Instances

The createInstance method can be used to create a new and independent instance with a separate configuration if needed:

const newCdk = cdk.createInstance(config)

Authenticated Requests

The following is a barebones example on how to use cocoda-sdk together with login-client.

Prerequisites:

See also the code comments inside the example.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Test</title>
</head>
<body>
<!-- login-client, cocoda-sdk -->
<script src="https://cdn.jsdelivr.net/npm/gbv-login-client@0"></script>
<script src="https://cdn.jsdelivr.net/npm/cocoda-sdk@2"></script>
<script>
// Initialize mapping registry at localhost:3000
const registry = CDK.cdk.initializeRegistry({
  provider: "MappingsApi",
  uri: "local:mappings",
  status: "http://localhost:3000/status",
})
// Note: This is an async function, so we might be dealing with race conditions here.
registry.init()
// Create client to connect to Login Server at localhost:3004
let client = new LoginClient("localhost:3004", { ssl: false })
let user
// Add listener for all event types
client.addEventListener(null, event => {
  switch (event.type) {
    case LoginClient.events.connect:
      // At this point, we don't know whether the user has logged in yet, but we can try
      console.log(registry.isAuthorizedFor({ type: "mappings", action: "create", user }))
      break
    case LoginClient.events.login:
      // Update user
      user = event.user
      // Now we know the user is logged in, so this should return true
      // Note that if the user is already logged in, this event will fire before connected
      console.log(registry.isAuthorizedFor({ type: "mappings", action: "create", user }))
      break
    case LoginClient.events.update:
      // Update user
      user = event.user
      break
    case LoginClient.events.about:
      // Register the server's public key in the registry
      registry.setAuth({ key: event.publicKey })
      break
    case LoginClient.events.token:
      // On every token update, update the token in the registry
      registry.setAuth({ bearerToken: event.token })
      break
  }
})
// Start connection to client
client.connect()
</script>
</body>
</html>

Note that for a real application, there are more things necessary:

You can find more in-depth examples here:

Methods

A cocoda-sdk instance itself offers only a handful of methods. The actual access to APIs happens through registries. The following list of methods assume either an instance of cocoda-sdk (cdk.someMethod) or an initialized registry (registry.someMethod). Documentation for registry methods is on a per-provider basis. While the API should be the same for a particular methods across providers, the details on how to use it might differ.

Methods for cocoda-sdk instance

Please refer to the documentation.

Registry Methods - General

registry.init

registry.isAuthorizedFor

registry.supportsScheme

registry.setAuth

registry.setRetryConfig

registry.getCancelTokenSource

Registry Methods - Concept Schemes

registry.getSchemes

registry.vocSearch

registry.vocSuggest

Registry Methods - Concepts

registry.getTop

registry.getConcepts

registry.getNarrower

registry.getAncestors

registry.search

registry.suggest

Registry Methods - Concordances

registry.getConcordances

registry.postConcordance

registry.putConcordance

registry.patchConcordance

registry.deleteConcordance

Registry Methods - Mappings

registry.getMappings

registry.getMapping

registry.postMapping

registry.postMappings

registry.putMapping

registry.patchMapping

registry.deleteMapping

registry.deleteMappings

Registry Methods - Annotations

registry.getAnnotations

registry.postAnnotation

registry.putAnnotation

registry.patchAnnotation

registry.deleteAnnotation

Registry Methods - Various

registry.getOccurrences

registry.getTypes

Errors

cocoda-sdk defines some custom errors.

const { errors } = require("cocoda-sdk") // CommonJS
import { errors } from "cocoda-sdk"

The following errors are defined:

For details about the errors, refer to the documentation.

Maintainers

Publish

Please work on the dev branch during development (or better yet, develop in a feature branch and merge into dev when ready).

When a new release is ready (i.e. the features are finished, merged into dev, and all tests succeed), run the included release script (replace "patch" with "minor" or "major" if necessary):

npm run release:patch

This will:

After running this, GitHub Actions will automatically publish the new version to npm. It will also create a new GitHub Release draft. Please edit and publish the release manually.

Contribute

PRs accepted.

Small note: If editing the README, please conform to the standard-readme specification.

License

MIT Copyright (c) 2021 Verbundzentrale des GBV (VZG)