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

@auxilium/datalynk-client

v0.8.2

Published

Datalynk client library

Downloads

187

Readme

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

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>

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();

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

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();

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

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