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 🙏

© 2025 – Pkg Stats / Ryan Hefner

s5-orm.js

v1.0.1

Published

JavaScript ORM for s5 API - Rails ActiveRecord-like interface

Readme

s5-orm.js

A JavaScript ORM for the s5 API - the on-demand storage platform.

About s5

s5 is an on-demand storage platform that provides a simple, RESTful API for storing and retrieving JSON documents. This library provides a Rails ActiveRecord-like interface for interacting with s5 collections, making it easy to work with your data in a familiar way.

Features

  • 🚀 ActiveRecord-like API - Familiar methods like find(), where(), create(), save()
  • 📊 Powerful Query DSL - Support for complex queries with operators like eq, gt, in, exists
  • 🔍 JSON Filtering - Filter documents using JSON-based criteria
  • 📄 Document Management - Create, read, update, delete operations with full CRUD support
  • TTL Support - Set time-to-live for documents
  • 🔄 Real-time Updates - Reload documents from the server

Installation

npm install s5.js

Quick Start

import S5 from 's5.js';

// Initialize the client
const s5 = new S5({
  apiKey: 'ak_your_prefix_your_secret'
});

// Get a collection
const User = s5.collection('users');

// Create a new user
const user = await User.create({
  name: 'John Doe',
  email: '[email protected]',
  status: 'active'
});

// Find users
const activeUsers = await User.where({
  q: ['eq(status,"active")']
});

console.log(activeUsers.documents);

Getting Started with s5

Before using this library, you'll need:

  1. An s5 account - Sign up at superstupidsimple.com
  2. An API key - Generate one in your s5 dashboard
  3. A collection - Create collections to organize your data

Usage

Basic Setup

import S5 from 's5.js';

const s5 = new S5({
  apiKey: 'ak_your_prefix_your_secret'
});

// Get a collection (like a Rails model)
const User = s5.collection('users');

Querying

// Find all users
const users = await User.where();

// Find with query DSL
const activeUsers = await User.where({
  q: ['eq(status,"active")', 'gt(score,100)']
});

// Find with JSON filter
const filteredUsers = await User.where({
  filter: {
    eq: { 'status': 'active' },
    gt: { 'score': 100 }
  }
});

// Find with ordering
const recentUsers = await User.where({
  order: ['-updated_at']
});

// Find first user
const firstUser = await User.first();

// Find by ID
const user = await User.find('user-123');

// Count users
const count = await User.count();

Pagination

s5.js supports pagination with configurable page sizes. By default, the API returns 25 documents per page (maximum 100).

// Basic pagination
const result = await User.where({
  limit: 10,  // 10 documents per page
  page: 1     // First page
});

console.log(result.documents); // Array of documents
console.log(result.pagination); // Pagination metadata

Pagination Response Structure

{
  documents: [
    // Array of Document objects
  ],
  pagination: {
    page: 1,        // Current page number
    pages: 5,       // Total number of pages
    count: 47,      // Total number of documents
    limit: 10,      // Documents per page
    from: 1,        // First document number on this page
    to: 10          // Last document number on this page
  }
}

Pagination Examples

// Get first page with 20 items
const page1 = await User.where({
  limit: 20,
  page: 1
});

// Get second page
const page2 = await User.where({
  limit: 20,
  page: 2
});

// Get last page (you can calculate this from pagination.pages)
const lastPage = await User.where({
  limit: 20,
  page: page1.pagination.pages
});

// Pagination with filtering
const activeUsers = await User.where({
  q: ['eq(status,"active")'],
  limit: 15,
  page: 1
});

Pagination Best Practices

// Helper function to get all pages
async function getAllPages(collection, options = {}) {
  const allDocuments = [];
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const result = await collection.where({
      ...options,
      page,
      limit: options.limit || 25
    });

    allDocuments.push(...result.documents);
    hasMore = page < result.pagination.pages;
    page++;
  }

  return allDocuments;
}

// Usage
const allUsers = await getAllPages(User, {
  q: ['eq(status,"active")']
});

Creating Documents

// Create a new user
const user = await User.create({
  name: 'John Doe',
  email: '[email protected]',
  status: 'active',
  score: 150
});

// Create with TTL
const tempUser = await User.create({
  name: 'Temp User'
}, {
  ttl_at: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
});

Working with Documents

// Get a document
const user = await User.find('user-123');

// Access data
console.log(user.data.name); // 'John Doe'
console.log(user.get('email')); // '[email protected]'

// Set data
user.set('status', 'inactive');
user.set('last_login', new Date());

// Save changes
await user.save();

// Update specific fields
await user.update({
  status: 'active',
  last_seen: new Date()
});

// Patch (merge data)
await user.patch({
  preferences: { theme: 'dark' }
});

// Reload from server
await user.reload();

// Delete
await user.destroy();

Query DSL Examples

// Equality
await User.where({ q: ['eq(status,"active")'] });

// Numeric comparisons
await User.where({ q: ['gt(score,100)', 'lt(age,65)'] });

// Array operations
await User.where({ q: ['in(role,["admin","user"])'] });

// Existence checks
await User.where({ q: ['exists(email,true)'] });

// Multiple conditions
await User.where({ 
  q: ['eq(status,"active")', 'gt(score,100)'],
  order: ['-created_at']
});

Error Handling

try {
  const user = await User.find('nonexistent');
  if (!user) {
    console.log('User not found');
  }
} catch (error) {
  console.error('API Error:', error.message);
}

API Reference

S5 Class

  • new S5(config) - Create S5 client
  • s5.collection(name) - Get a collection

Document Class

Static Methods (Class Methods)

  • Document.where(options) - Find documents with pagination support
  • Document.find(id) - Find by ID
  • Document.first(options) - Find first document
  • Document.count(options) - Count documents
  • Document.create(data, options) - Create new document

Query Options

  • q - Array of query DSL strings (e.g., ['eq(status,"active")'])
  • filter - JSON filter object
  • order - Array of ordering strings (e.g., ['-updated_at'])
  • limit - Number of documents per page (1-100, default: 25)
  • page - Page number (default: 1)

Instance Methods

  • document.save() - Save (create or update)
  • document.update(data) - Update document
  • document.patch(data) - Merge data
  • document.destroy() - Delete document
  • document.reload() - Reload from server
  • document.get(key) - Get nested value
  • document.set(key, value) - Set nested value

Properties

  • document.persisted - Check if document is saved
  • document.id - Document ID
  • document.data - Document data
  • document.version - Document version
  • document.created_at - Creation timestamp
  • document.updated_at - Last update timestamp

Query DSL Reference

Operators

  • eq(field,value) - Equality
  • ne(field,value) - Not equal
  • gt(field,value) - Greater than
  • gte(field,value) - Greater than or equal
  • lt(field,value) - Less than
  • lte(field,value) - Less than or equal
  • in(field,values) - In array
  • nin(field,values) - Not in array
  • contains(field,value) - JSON contains
  • exists(field,true/false) - Field exists

Ordering

  • order: ['field'] - Ascending
  • order: ['-field'] - Descending
  • order: ['field', '-other'] - Multiple fields

Examples

// Complex query
await User.where({
  q: [
    'eq(status,"active")',
    'gt(score,100)',
    'in(role,["admin","moderator"])'
  ],
  order: ['-last_login', 'name'],
  limit: 50
});

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Links