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

@lyra/client

v0.3.0

Published

Client for retrieving data from Lyra

Downloads

25

Readme

@lyra/client

npm version

Javascript client for Lyra. Works in node.js and modern browsers (older browsers needs a Promise polyfill).

Requirements

Lyra Client requires the JavaScript runtime to have a global ES6-compliant Promise available. If your runtime environment doesn't provide a spec compliant Promise implementation, we recommend using native-promise-only, es6-promise or another spec-compliant implementation. See this article for more information.

Installation

The client can be installed from npm:

npm install --save @lyra/client

API

const lyraClient = require('@lyra/client')
const client = lyraClient({
  dataset: 'bikeshop',
  token: 'lyra-auth-token', // or leave blank to be anonymous user
})

const client = lyraClient(options)

Initializes a new Lyra Client. Required options are apiHost and dataset.

Fetch a single document

client.getDocument('bike-123').then(bike => {
  console.log(`${bike.name} (${bike.seats} seats)`)
})

Performing queries

const query = '*[_type == "bike" && seats >= $minSeats] {name, seats}'
const params = {minSeats: 2}

client.fetch(query, params).then(bikes => {
  console.log('Bikes with more than one seat:')
  bikes.forEach(bike => {
    console.log(`${bike.name} (${bike.seats} seats)`)
  })
})

client.fetch(query, params = {})

Perform a query using the given parameters (if any).

Listening to queries

const query = '*[_type == "comment" && authorId != $ownerId]'
const params = {ownerId: 'bikeOwnerUserId'}

const subscription = client.listen(query, params).subscribe(comment => {
  console.log(`${comment.author} commented: ${comment.text}`)
})

client.listen(query, params = {}, options = {includeResult: true})

Open a query that listens for updates on matched documents, using the given parameters (if any). The return value is an RxJS Observable. When calling subscribe() on the observable, a subscription is returned which can be used to unsubscribe from the query.

The objects which are emitted always contain mutation, which is an object containing the mutation which triggered the document to appear as part of the query.

By default, the emitted object will also contain a result property, which contains the document with the mutation applied to it. In case of a delete mutation, this property will not be present, however. You can also tell the client not to return the document (to save bandwidth, or in cases where the mutation or the document ID is the only relevant factor) by setting the includeResult property to false in the options.

Likewise, you can also have the client return the document before the mutation was applied, by settingincludePreviousRevision to true in the options, which will include a previous property in each emitted object.

Creating documents

const doc = {
  _type: 'bike',
  name: 'Lyra Tandem Extraordinaire',
  seats: 2
}

client.create(doc).then(res => {
  console.log(`Bike was created, document ID is ${res._id}`)
})

client.create(doc)

Create a document. Argument is a plain JS object representing the document. It must contain a _type attribute. It may contain an _id. If an ID is not specified, it will automatically be created.

Creating/replacing documents

const doc = {
  _id: 'my-bike',
  _type: 'bike',
  name: 'Lyra Tandem Extraordinaire',
  seats: 2
}

client.createOrReplace(doc).then(res => {
  console.log(`Bike was created, document ID is ${res._id}`)
})

client.createOrReplace(doc)

If you are not sure whether or not a document exists but want to overwrite it if it does, you can use the createOrReplace() method. When using this method, the document must contain an _id attribute.

Creating if not already present

const doc = {
  _id: 'my-bike',
  _type: 'bike',
  name: 'Lyra Tandem Extraordinaire',
  seats: 2
}

client.createIfNotExists(doc).then(res => {
  console.log('Bike was created (or was already present)')
})

client.createIfNotExists(doc)

If you want to create a document if it does not already exist, but fall back without error if it does, you can use the createIfNotExists() method. When using this method, the document must contain an _id attribute.

Patch/update a document

client
  .patch('bike-123') // Document ID to patch
  .set({inStock: false}) // Shallow merge
  .inc({numSold: 1}) // Increment field by count
  .commit() // Perform the patch and return a promise
  .then(updatedBike => {
    console.log('Hurray, the bike is updated! New document:')
    console.log(updatedBike)
  })
  .catch(err => {
    console.error('Oh no, the update failed: ', err.message)
  })

client.patch(docId).set(partialDoc).inc({key: value}).commit()

Modify a document. patch takes a document ID. set merges the partialDoc with the stored document. inc increments the given field with the given numeric value. commit executes the given patch. Returns the updated object.

Patch a document only if revision matches

You can use the ifRevisionId(rev) method to specify that you only want the patch to be applied if the stored document matches a given revision.

client
  .patch('bike-123')
  .ifRevisionId('previously-known-revision')
  .set({title: 'Little Red Tricycle'})
  .commit()

Delete a document

client
  .delete('bike-123')
  .then(res => {
    console.log('Bike deleted')
  })
  .catch(err => {
    console.error('Delete failed: ', err.message)
  })

client.delete(docId)

Delete a document. Parameter is a document ID.

Multiple mutations in a transaction

const namePatch = client.patch('bike-310').set({name: 'A Bike To Go'})

client
  .transaction()
  .create({name: 'Lyra Tandem Extraordinaire', seats: 2})
  .delete('bike-123')
  .patch(namePatch)
  .commit()
  .then(res => {
    console.log('Whole lot of stuff just happened')
  })
  .catch(err => {
    console.error('Transaction failed: ', err.message)
  })

client.transaction().create(doc).delete(docId).patch(patch).commit()

Create a transaction to perform chained mutations.

client
  .transaction()
  .create({name: 'Lyra Tandem Extraordinaire', seats: 2})
  .patch('bike-123', p => p.set({inStock: false}))
  .commit()
  .then(res => {
    console.log('Bike created and a different bike is updated')
  })
  .catch(err => {
    console.error('Transaction failed: ', err.message)
  })

client.transaction().create(doc).patch(docId, p => p.set(partialDoc)).commit()

A patch can be performed inline on a transaction.

Clientless patches & transactions

Transactions and patches can also be built outside the scope of a client:

const lyraClient = require('@lyra/client')
const client = lyraClient({
  apiHost: 'https://the.lyra.api',
  dataset: 'bikeshop'
})

// Patches:
const patch = new lyraClient.Patch('<documentId>')
client.mutate(patch.inc({count: 1}).unset(['visits']))

// Transactions:
const transaction = new lyraClient.Transaction()
  .create({_id: '123', name: 'FooBike'})
  .delete('someDocId')

client.mutate(transaction)

const patch = new lyraClient.Patch(docId)

const transaction = new lyraClient.Transaction()

An important note on this approach is that you cannot call commit() on transactions or patches instantiated this way, instead you have to pass them to client.mutate()

Uploading assets

Assets can be uploaded using the client.assets.upload(...) method.

client.asset.upload(type: 'file' | image', body: File | Blob | Buffer | NodeStream, options = {}): Promise<AssetDocument>

👉 Read more about assets in Lyra

Examples: Uploading assets from Node.js

// Upload a file from the file system
client.assets
  .upload('file', fs.createReadStream('myFile.txt'), {filename: 'myFile.txt'})
  .then(document => {
    console.log('The file was uploaded!', document)
  })
  .catch(error => {
    console.error('Upload failed:', error.message)
  })
// Upload an image file from the file system
client.assets
  .upload('image', fs.createReadStream('myImage.jpg'), {
    filename: 'myImage.jpg'
  })
  .then(document => {
    console.log('The image was uploaded!', document)
  })
  .catch(error => {
    console.error('Upload failed:', error.message)
  })

Examples: Uploading assets from the Browser

// Create a file with "foo" as its content
const file = new File(['foo'], 'foo.txt', {type: 'text/plain'})
// Upload it
client.assets
  .upload('file', file)
  .then(document => {
    console.log('The file was uploaded!', document)
  })
  .catch(error => {
    console.error('Upload failed:', error.message)
  })
// Draw something on a canvas and upload as image
const canvas = document.getElementById('someCanvas')
const ctx = canvas.getContext('2d')
ctx.fillStyle = '#f85040'
ctx.fillRect(0, 0, 50, 50)
ctx.fillStyle = '#fff'
ctx.font = '10px monospace'
ctx.fillText('Lyra', 8, 30)
canvas.toBlob(uploadImageBlob, 'image/png')

function uploadImageBlob(blob) {
  client.assets
    .upload('image', blob, {contentType: 'image/png', filename: 'someText.png'})
    .then(document => {
      console.log('The image was uploaded!', document)
    })
    .catch(error => {
      console.error('Upload failed:', error.message)
    })
}

Examples: Specify image metadata to extract

// Extract palette of colors as well as GPS location from exif
client.assets
  .upload('image', someFile, {extract: ['palette', 'location']})
  .then(document => {
    console.log('The file was uploaded!', document)
  })
  .catch(error => {
    console.error('Upload failed:', error.message)
  })

Deleting an asset

Deleting an asset document will also trigger deletion of the actual asset.

client.delete(id: string): Promise
client.delete('image-abc123_someAssetId-500x500-png').then(result => {
  console.log('deleted imageAsset', result)
})

Get client configuration

const config = client.config()
console.log(config.dataset)

client.config()

Get client configuration.

Set client configuration

client.config({dataset: 'newDataset'})

client.config(options)

Set client configuration. Required options are apiHost and dataset.