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

onpage-js

v1.1.26

Published

[![npm version](https://badge.fury.io/js/onpage-js.svg)](https://badge.fury.io/js/onpage-js)

Downloads

109

Readme

On Page ® JS library

npm version

With this library you can easy query your data using an On Page ® API token.

Installation

npm install onpage-js
# or
yarn add onpage-js

Usage

Setup

Load a project using an API Token

import { Schema } from 'onpage-js'
const schema = await Schema.load({ token: 'abc' })
console.log(schema.label, 'is ready')

Load a project using an User Token (for internal use)

const api = new Api({ token: 'abc', is_user_mode: true })
const schema = api.loadSchema(123)

Get structure information

// Retrieve info about the schema:
console.log(schema.label, schema.langs)

// Retrieve a resource given its name or ID
let res = schema.resource('products')
res.fields.forEach(field => {
  console.log(field.label)
})

Query your data

// Retrieve all records of a resource (returns an array of Thing)
let products = await schema
  .resource('products') // This is the table (aka Resource) name
  .query() // Create a query on the Resource
  .all() // finalize the query, get all the elemtents

// Get only the first item
let prod = await schema.query('products').first()
console.log('hello', prod.val('name'))

// Count the items matching a query
let in_stock = await schema
  .query('products')
  .where('quantity', '>', 0)
  .where('pending', '>', 0)
  .count()

Filters

// Retrieve the record with a specific id
let my_product = schema.query('products').find(42)

// Other filters
let valid_products = schema
  .query('products')
  .where('name', 'like', 'shoes') // you can specify a different operator
  .where('category.name', 'Nike') // you can query relations
  .where('is_on_sale', true) // = is the default comparison
  .where('dimension', '>', 10) // you get it
  .all()

Get thing values

You can use the val() or file() method to retrieve a single value from the field:

let cat = await schema.query('categories').first()
console.log(cat.val('name'))
console.log(cat.val('dimension'))
console.log(cat.val('description', 'fr')) // you can specify a language

// For multi-value fields, you can retrieve all values using the `values()` method:
console.log(cat.values('bullet_points')) // [ "First value", "Second value" ]

These functions also work on related items:

let cat = await schema.query('categories').with('products.colors').first()
console.log(cat.values('products.colors.name')) // ["green", "red", "blue"]

Files

For image and file fields, the returned value will be an instance of OpFile. To get a file or image url use the .link() function. The link will point to the original file.

product.file('specsheet').name // icecream-spec.pdf
product.file('specsheet').token // R417C0YAM90RF
product.file('specsheet').link() // https://storage.onpage.it/FILEHASH/icecream-spec.pdf

To turn images into a thumbnail add an array of options as shown below:

// maintain proportions width 200px
prod.val('cover_image').link({'x' : 200})

// maintain proportions height 100px
prod.val('cover_image').link({'y' : 100})

// crop image to width 200px and height 100px
prod.val('cover_image').link({'x' : 200, 'y' : 100})

// maintain proportions and contain in a rectangle of width 200px and height 100px
prod.val('cover_image').link({'x' : 200, 'y' : 100, 'contain' : true))

// convert the image to png (default is jpg)
prod.val('cover_image').link({'x' : 200, 'ext' : 'png'})

Get thing relations

let cat = await schema.query('categories').first()

// This will do 1 API call to download the subcategories
let subcategories = await cat.rel('subcategories')

// Now you can access the subcategories
subcategories.forEach(subcategory => {
  console.log(subcategory.val('name'))
})

// You can also get nested relations in one shot
let products = await cat.rel('subcategories.products')

Preload thing relations

The previous example will execute an API call every time you call the rel() method. Usually it is a good idea to preload relations so that only one API call is done, resulting in faster execution.

let cat = await schema.query('categories').with('subcategories').first()

// This will not execute any API call
let subcategories = await cat.rel('subcategories')

// If you don't want to use await, you can use relSync() method to retrieve loaded items
// NOTE: This will only work if the relation has been preloaded
let subcategories = cat.relSync('subcategories')

subcategories.forEach(subcategory => {
  console.log(subcategory.val('name'))
})

// You can also preload nested subcategories
let cat = await schema
  .query('categories')
  .with('subcategories.articles.colors')
  .first()

// Or many relations at once:
let product = await schema
  .query('products')
  .with(['category', 'variants.size', 'variants.color'])
  .first()

Filter related items

// If you need to filter the related items you want to download, you can do this:
const category = schema
  .query('categories')
  .with('subcategories.articles.colors')
  .filterRelation('subcategories.articles', q => {
    q.where('is_online', true)
  })
  .first()

// Only online articles will be downloaded
const articles = category.relSync('subcategories.articles')

Set relation related items

// You can also limit the fields on a related item
const products = schema
  .query('products')
  .with(['colors'])
  .loadRelationFields('colors', ['name', 'image']) // only load 2 fields for the "color" relation
  .all()

Creating and updating things

To create or update a record, you need to create a Thing Editor. There are two ways to get a Thing Editor:

  1. Using the Resource Writer (best for bulk updates)
  2. Calling .editor() on a Thing (best for one-thing updates)

Using the Resource Writer (first method)

This class allows you to edit many records at once. You can easily obtain the editor calling:

const writer = schema.resource('categories').writer()

Now that you have a Resource Writer, you can use it to create things:

const editor = writer.createThing()
editor.set('name', 'Element 1')
editor.setRel('category', [12345]) // array with category IDs

...and to update existing things:

const editor = writer.updateThing(736251) // The id of the element you want to update
editor.set('description', 'Element 1 description')

Finally, you need to send the request to the On Page server:

// this will create and update all the things as requested above
await writer.save()

Updating a single item (second method)

const product = await schema
  .query('products')
  .where('name', 'Plastic Duck')
  .first()

editor = product.editor()
editor.set('description', 'This yellow plastic duck will be your best friend')
editor.set('description', '这只黄色塑料鸭将是你最好的朋友', 'zh') // you can specify language

// Save all the edits at once using the save method
await editor.save()

Limiting modified languages

By default, even if you update a single language, the writer will delete the data on other languages. If you only need to edit certain languages and maintain the current values for the others, you can specify which languages you are working on as follows:

// Update the chinese description without deleting the english description:
editor = product.editor()
editor.setLangs(['zh'])
editor.set('description', '这只')
await editor.save()

Updating translations

Just add the language code as the third argument to the set function:

// Update the value in the default language
editor.set('description', 'This yellow plastic duck will be your best friend')

// Specify another the language
editor.set('description', '这只黄色塑料鸭将是你最好的朋友', 'zh')

Updating files

You can upload a file using a public URL:

editor.set('image', 'https://mysite.com/bird_cover.jpg') // specify file by url

Updating multivalue fields

For multivalue fields you only need to replace .set with .setValues and pass an array of values as the second argument:

editor.setValues('bullet_points', [
  'Durable plastic',
  'Bright yellow color',
  'Compostable',
])

Updating relations

To update relations, you can use the .setRel(relation_name, related_ids):

editor.setRel('features', [425790, 547023, 240289])

Offline mode

You can download data for offline usage by calling schema.createSnapshot() which will download all the things in the project and return an object that contains information about the schema and its elements (the things) which can be easily serialized.

// Download all data from the project
const serialized_data = await schema.createSnapshot()

// Use the snapshot to create a new Schema instance in offline mode
const offline_schema = Schema.fromSnapshot(serialized_data)

// This schema is now in offline mode, which means all queries are run locally (e.g. without internet connection)
// All features should work, if something does not, please open a issue in Github
await offline_schema.query('products').count()

Example: store and restore the snapshot in the localStorage:

// Download and store the project
async function serializeToLocalStorage() {
  const online_schema = await Schema.load({ token: 'abc' })
  const serialized_data = await online_schema.createSnapshot()
  localStorage.setItem('offline-data', JSON.stringify(serialized_data))
}

function deserializeFromLocalStorage(): Schema {
  const serialized_data = JSON.parse(localStorage.getItem('offline-data'))
  const offline_schema = Schema.fromSnapshot(serialized_data)
  return offline_schema
}