A JavaScript ORM for the s5 API - the on-demand storage platform.
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.
- 🚀 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
npm install s5.jsimport 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: 'john@example.com',
status: 'active'
});
// Find users
const activeUsers = await User.where({
q: ['eq(status,"active")']
});
console.log(activeUsers.documents);Before using this library, you'll need:
- An s5 account - Sign up at superstupidsimple.com
- An API key - Generate one in your s5 dashboard
- A collection - Create collections to organize your data
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');// 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();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{
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
}
}// 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
});// 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")']
});// Create a new user
const user = await User.create({
name: 'John Doe',
email: 'john@example.com',
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
});// Get a document
const user = await User.find('user-123');
// Access data
console.log(user.data.name); // 'John Doe'
console.log(user.get('email')); // 'john@example.com'
// 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();// 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']
});try {
const user = await User.find('nonexistent');
if (!user) {
console.log('User not found');
}
} catch (error) {
console.error('API Error:', error.message);
}new S5(config)- Create S5 clients5.collection(name)- Get a collection
Document.where(options)- Find documents with pagination supportDocument.find(id)- Find by IDDocument.first(options)- Find first documentDocument.count(options)- Count documentsDocument.create(data, options)- Create new document
q- Array of query DSL strings (e.g.,['eq(status,"active")'])filter- JSON filter objectorder- Array of ordering strings (e.g.,['-updated_at'])limit- Number of documents per page (1-100, default: 25)page- Page number (default: 1)
document.save()- Save (create or update)document.update(data)- Update documentdocument.patch(data)- Merge datadocument.destroy()- Delete documentdocument.reload()- Reload from serverdocument.get(key)- Get nested valuedocument.set(key, value)- Set nested value
document.persisted- Check if document is saveddocument.id- Document IDdocument.data- Document datadocument.version- Document versiondocument.created_at- Creation timestampdocument.updated_at- Last update timestamp
eq(field,value)- Equalityne(field,value)- Not equalgt(field,value)- Greater thangte(field,value)- Greater than or equallt(field,value)- Less thanlte(field,value)- Less than or equalin(field,values)- In arraynin(field,values)- Not in arraycontains(field,value)- JSON containsexists(field,true/false)- Field exists
order: ['field']- Ascendingorder: ['-field']- Descendingorder: ['field', '-other']- Multiple fields
// Complex query
await User.where({
q: [
'eq(status,"active")',
'gt(score,100)',
'in(role,["admin","moderator"])'
],
order: ['-last_login', 'name'],
limit: 50
});Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
- GitHub: https://github.com/petersonwynkooptech/s5.js
- npm: https://www.npmjs.com/package/s5.js
- s5 Platform: https://superstupidsimple.com