@auxilium/datalynk-client
TypeScript icon, indicating that this package has built-in type declarations

0.8.2 • Public • Published

Datalynk Client Library

pipeline status


Datalynk client library to integrate JavaScript clients with the Datalynk API.

Table of Contents

Quick Start

  1. Install the client library
npm install --save @auxilium/datalynk-client
  1. Optional: Build Datalynk models
$ npx datalynk-models
Output (src/models):
Spoke: spoke
Login: username
Password: ********
  1. Create an API object & start making requests
import {API} from '@auxilium/datalynk-client';

const api = new API('https://spoke.auxiliumgroup.com');
const resp = await api.request({'$/auth/current':{}});

Documentation

Full API Documentation

Integration

This library is written with vanilia JS & has no framework dependencies allowing easy integration with any front-end website. Here is some boilerplate to get you going:

Angular

File: /src/services/datalynk.service.ts

import {Injectable} from '@angular/core';
import {Api, Slice} from '@auxilium/datalynk-client';
import {environment} from '../environment/environment';
import {Contact} from '../models/contact';
import {Slices} from '../models/slices';

declare global {
  interface Window {
    api: Api;
  }
}

@Injectable({providedIn: 'root'})
export class DatalynkApi extends Api {
  contacts!: Slice<Contact>;

  constructor() {
    // Create API object & expose to window
    super(environment.api, {/* options */});
    window.api = this;

    // Handle logging in
    this.auth.handleLogin('spoke', {/* login UI options */});

    // Create store to cache slice data
    this.contacts = this.slice<Contact>(Slices.Contact);
  }
}

Node / Vue

File: /src/services/datalynk.service.ts

import {Api} from '@auxilium/datalynk-client';
import {environment} from '../environment/environment';
import {Contact} from '../models/contact';
import {Slices} from '../models/slices';

// Create API object & expose to window
export const api = window.api = new Api(environment.api, {/* options */});

// Handle logging in
api.auth.handleLogin('spoke', {/* login UI options */});

// Create store to cache slice data
export const contacts = api.slice<Contact>(Slices.Contact);

Vanilia JS

File: /index.html

<script type="module">
  import {Api} from '@auxilium/datlaynk-client/dist/index.mjs';

  // Create API object & expose to window
  var api = new Api('https://spoke.auxiliumgroup.com', /* options */);

  // Handle logging in
  api.auth.handleLogin('spoke', {/* login UI options */});

  // Create store to cache slice data
  var contacts = api.slice(12345);
</script>

Build Models

This library comes with a command line tool for developers to automatically create Typescript models from the Datalynk metadata.

This takes most of the manual labour out of manually mapping the data & provides type safety.

  1. Simply run the tool:
$ npx datalynk-models
Output (src/models):
Spoke: spoke
Login: username
Password: ********
  1. Import models:
import {Slices} from 'models/slices'; // Import slices map
import {Contact} from 'models/contact'; // Import model for slice we will be using

const contacts: Contact[] = await api.slice<Contact>(Slices.Contact)
                                     .select()
                                     .exec().rows();

Authentication

Login flow

This library comes with some logic to automatically handle the login flow & should be called at the startup of your application:

  1. It will check the URL for a token param: ?datalynkToken=...
  2. It will check the localStorage for a saved token
  3. It will prompt the user to login via UI
  4. Reload page if token changed
await api.auth.handleLogin('spoke', {
  background: 'url("...")', // CSS URL or hex color
  color: '#ff0000', // hex color
  title: '<img alt="logo" src="..." />', // text or HTML
  titleColor: '#ffffff' // Color of title text
});

Login UI

Alternatively you can manage the login prompt manually:

const prompt = api.auth.loginPrompt('spoke', options);
await prompt.wait; // Wait for the user to login/close the prompt
prompt.close(); // Close prompt manually

Programatically

Manually login programatically:

const user = await api.auth.login('spoke', 'username', 'password', '2faCode');

Slice Engine

This library comes with LINQ style query language to help make interacting with Slices easier by providing types & intelisense.

Select

// Get a single record
const row = await api.slice<T>(12345)
                     .select(12345)
                     .exec().row();

// Get all slice records
const rows = await api.slice<T>(12345)
                      .select()
                      .exec().rows();

// Advanced queries
const rows = await api.slice<T>(12345)
                      .select()
                      .where('field1', '==', 'value')
                      .fields({'field1': 'field2'})
                      .order('field2', true /* ascending */)
                      .limit(10)
                      .exec().rows();                      

Insert

// Insert record
const key = await api.slice<Contact>(12345)
                     .insert({first: 'Bilbo', last: 'Baggins'})
                     .exec().key();

// Insert multiple rows
const keys = await api.slice<Contacts>(12345)
                      .insert([
                        {first: 'Darth', last: 'Vader'},
                        {first: 'John', last: 'Snow'}
                      ])
                      .exec().keys();

Update

// Update a record
const success = await api.slice(12345)
                         .update({id: 1, first: 'James', last: 'Kirk'})
                         .exec().key();

// Update multiple rows with where
await api.slice(12345)
         .update({evil: true})
         .where({first: 'Darth'})
         .exec().keys();

Delete

// Delete a record
const success = await api.slice(12345)
                         .delete(12345)
                         .exec().key();

// Dlete multiple rows with where
await api.slice(12345)
         .delete()
         .where({first: 'Darth'})
         .exec().keys();

Sockets

Options

The socket can have it's endpoint overriden or be turned off by setting it to false:

const api = new Api('https://spoke.auxiliumgroup.com', {
  socket: false, // Disable
  // socket: 'http://localhost:3000', // Override
});

Slice Engine

The Slice Engine's cache can be sycned with the server & subscribed to using RXJS:

// Create cache/store
const contacts = api.slice<Contact>(Slices.Contact);

// Enable syncing
contacts.sync();

// Use RXJS to listen for events
contacts.sync().pipe(...).subscribe((cache: Contact[]) => {...});
// Or using Angular templates
'{{ contacts.sync() | async }}'

// Disable syncing
contacts.sync(false);

Socket Events

Alternatively socket events can be listened to directly using callbacks:

api.socket.sliceEvents(123, callbackFn(event)); // Listen to a specific slice
api.socket.addListener(callbackFn(event)); // listen to all socket events

Uploads

A file URL can be created from the file ID

const url = api.files.get(12345);

Uploading files to datalynk is done by first uploading the file as form-data & then creating a reference to the upload ID in a slice.

// Get files from file input
const files = document.querySelector('#upload').files;

// Upload file
api.files.upload(files).then(uploaded => {
  // Associate with record
  const slice = 12345, row: 123;
  api.files.associate(uploaded.map(r => r.id), slice, row, 'field');
});

// OR do it all at once
api.files.upload(files, {slice: 12345, row: 1234, field: 'abc'});

Readme

Keywords

none

Package Sidebar

Install

npm i @auxilium/datalynk-client

Weekly Downloads

20

Version

0.8.2

License

none

Unpacked Size

213 kB

Total Files

25

Last publish

Collaborators

  • auxilium