superleap-sdk
v2.4.1
Published
A comprehensive JavaScript SDK for interacting with SuperLeap CRM API with Django-like query builder
Readme
SuperLeap SDK v2.0.0
A comprehensive JavaScript SDK for interacting with SuperLeap CRM API with Django-like query builder functionality, advanced caching, and optimized performance.
Features
- 🚀 Django-like Query Builder: Familiar ORM-style querying with method chaining
- ⚡ Lazy Execution: Await query builders directly for intuitive querying
- 📝 Full CRUD Operations: Create, read, update, and delete records
- 🔍 Advanced Filtering: Support for complex filters with AND/OR conditions
- 🎯 TypeScript Support: Full TypeScript definitions included
- 📊 Pagination: Built-in pagination support
- 🔄 Relationship Support: Handle related objects and foreign keys
- 🎨 Modern API: Clean, intuitive interface with promises/async-await
- 📦 Zero Dependencies: Pure JavaScript with no external dependencies
- 🚀 Advanced Caching: Intelligent caching with TTL support and cache invalidation
- 🔧 Smart Schema Management: Lazy-loaded schema with field validation
- 📈 Performance Optimized: Minimal API calls with opt-in caching strategies
Installation & Usage
For React/Vue/Angular Apps (Module Import)
Installation
# Via npm
npm install superleap-sdk
# Via yarn
yarn add superleap-sdkUsage in React Component
import { createSuperLeapSDK } from "superleap-sdk";
// or
import SuperLeapSDK from "superleap-sdk";
function MyComponent() {
const [records, setRecords] = useState([]);
useEffect(() => {
// Initialize SDK with advanced caching
const sdk = createSuperLeapSDK({
apiKey: "your-api-key",
baseUrl: "https://app.superleap.dev/api/v1",
clientId: "your-client-id",
clientSecret: "your-client-secret",
cache: {
enabled: true,
maxSize: 2000,
defaultTTL: 5 * 60 * 1000, // 5 minutes
ttl: {
schema: 30 * 60 * 1000, // 30 minutes
records: 2 * 60 * 1000, // 2 minutes
count: 60 * 1000, // 1 minute
user: 10 * 60 * 1000, // 10 minutes
},
},
});
// Use the SDK with lazy execution and caching
const loadData = async () => {
const userModel = sdk.getModel("user");
// Enable caching for this query
const users = await userModel
.select("name", "email", "status")
.where({ status: "active" })
.cache({ ttl: 60 * 1000 }); // Cache for 1 minute
setRecords(users);
};
loadData();
}, []);
return (
<div>
{records.map((record) => (
<div key={record.id}>{record.get("name")}</div>
))}
</div>
);
}TypeScript Usage
import {
SuperLeapSDK,
createSuperLeapSDK,
Model,
RecordInstance,
} from "superleap-sdk";
const sdk: SuperLeapSDK = createSuperLeapSDK({
apiKey: "your-api-key",
baseUrl: "https://app.superleap.dev/api/v1",
clientId: "your-client-id",
clientSecret: "your-client-secret",
});
// Full type safety
const userModel: Model = sdk.getModel("user");
const users: RecordInstance[] = await userModel.select("name", "email").cache();For Vanilla JS/HTML (Script Tag)
Installation
<!-- Via CDN -->
<script src="https://cdn.jsdelivr.net/npm/superleap-sdk@latest/superleap.js"></script>
<!-- Or download and include locally -->
<script src="path/to/superleap.js"></script>Usage in HTML/JavaScript
<!DOCTYPE html>
<html>
<head>
<title>SuperLeap SDK Example</title>
<script src="https://cdn.jsdelivr.net/npm/superleap-sdk@latest/superleap.js"></script>
</head>
<body>
<div id="results"></div>
<script>
// SDK is automatically available as global
const sdk = createSuperLeapSDK({
apiKey: "your-api-key",
baseUrl: "https://app.superleap.dev/api/v1",
clientId: "your-client-id",
clientSecret: "your-client-secret",
cache: { enabled: true },
});
// Alternative: Direct instantiation
// const sdk = new SuperLeapSDK({...options});
async function loadUsers() {
try {
const userModel = sdk.getModel("user");
// Await the query builder directly with caching
const users = await userModel
.select("name", "email")
.where({ status: "active" })
.cacheTTL(60 * 1000); // Cache for 1 minute
const resultsDiv = document.getElementById("results");
resultsDiv.innerHTML = users
.map(
(user) => `<div>${user.get("name")} - ${user.get("email")}</div>`
)
.join("");
} catch (error) {
console.error("Error:", error);
}
}
// Load data when page loads
loadUsers();
</script>
</body>
</html>Global Variables Available
// These are automatically available in vanilla JS:
window.SuperLeapSDK; // Constructor class
window.createSuperLeapSDK; // Factory function
window.DataType; // Data type constants
window.RelationshipType; // Relationship type constants
window.CacheManager; // Cache manager class
window.CacheEntry; // Cache entry class
// Usage examples:
const sdk1 = new SuperLeapSDK({ apiKey: "key" });
const sdk2 = createSuperLeapSDK({ apiKey: "key" });
console.log(DataType.Email); // 11
console.log(RelationshipType.OneToMany); // 2Quick Start
Initialize the SDK
const sdk = createSuperLeapSDK({
apiKey: "your-bearer-token", // Required
baseUrl: "https://app.superleap.dev/api/v1", // Optional
clientId: "your-client-id", // Required
clientSecret: "your-client-secret", // Required
cache: {
// Optional - Advanced caching
enabled: true,
maxSize: 2000,
defaultTTL: 5 * 60 * 1000,
ttl: {
schema: 30 * 60 * 1000, // 30 minutes
records: 2 * 60 * 1000, // 2 minutes
count: 60 * 1000, // 1 minute
user: 10 * 60 * 1000, // 10 minutes
},
},
});Basic CRUD Operations
// Initialize the SDK
const sdk = createSuperLeapSDK({
apiKey: "your-api-key",
baseUrl: "https://app.superleap.dev/api/v1",
clientId: "your-client-id",
clientSecret: "your-client-secret",
});
// Get a model
const userModel = sdk.getModel("user");
// Create a new record
const newUser = await userModel.create({
name: "John Doe",
email: "[email protected]",
status: "active",
});
// Query records with caching - await the query builder directly
const activeUsers = await userModel
.select("name", "email", "status")
.where({ status: "active" })
.orderBy("-created_at")
.limit(10)
.cache(); // Enable caching
// Update a record (use model.update instead of deprecated record.update)
const updatedUser = await userModel.update(newUser.id, {
name: "John Smith",
});
// Delete a record
await userModel.delete(newUser.id);Documentation
Initialization
const sdk = createSuperLeapSDK({
apiKey: "your-bearer-token", // Required
baseUrl: "https://app.superleap.dev/api/v1", // Optional
clientId: "your-client-id", // Required
clientSecret: "your-client-secret", // Required
cache: {
// Optional - Advanced caching
enabled: true, // Enable/disable caching (default: true)
maxSize: 2000, // Maximum cache entries (default: 1000)
defaultTTL: 5 * 60 * 1000, // Default TTL in milliseconds (default: 5 minutes)
ttl: {
// Specific TTL settings
schema: 30 * 60 * 1000, // Schema cache TTL (default: 30 minutes)
records: 2 * 60 * 1000, // Record queries TTL (default: 2 minutes)
count: 60 * 1000, // Count queries TTL (default: 1 minute)
user: 10 * 60 * 1000, // User data TTL (default: 10 minutes)
},
},
});Models
Get a model instance for any SuperLeap object:
const model = sdk.getModel("objectSlug");
// or
const model = sdk.model("objectSlug");Query Builder
The query builder provides a Django-like interface with lazy execution - you can await query builders directly:
Basic Queries
// Get all records
const records = await model.selectAll();
// Get first 10 records
const records = await model.selectAll().limit(10);
// Get first record
const record = await model.selectAll().first();
// Count records
const count = await model.selectAll().count();
// Check if records exist
const exists = await model.selectAll().exists();Field Selection
// Select specific fields
const records = await model.select("name", "email", "created_at");
// Select all fields
const records = await model.selectAll();
// Select related fields (dot notation)
const records = await model.select("user.name", "user.email");Filtering
// Simple where conditions
const records = await model
.select("name", "email")
.where({ status: "active", type: "premium" });
// Field-specific filters
const records = await model
.select("name", "email")
.exact("status", "active")
.contains("name", "John")
.gt("age", 18)
.in("department", ["sales", "marketing"]);Available Filter Methods
| Method | Description | Example |
| ---------------------------- | -------------------------------- | -------------------------------------- |
| exact(field, value) | Exact match | .exact('status', 'active') |
| iexact(field, value) | Case-insensitive exact match | .iexact('status', 'ACTIVE') |
| notexact(field, value) | Not exact match | .notexact('status', 'inactive') |
| notiexact(field, value) | Case-insensitive not exact match | .notiexact('status', 'INACTIVE') |
| contains(field, value) | Contains text (case-sensitive) | .contains('name', 'John') |
| icontains(field, value) | Case-insensitive contains | .icontains('name', 'john') |
| startswith(field, value) | Starts with | .startswith('name', 'John') |
| endswith(field, value) | Ends with | .endswith('email', '@gmail.com') |
| in(field, values) | In array | .in('status', ['active', 'pending']) |
| notin(field, values) | Not in array | .notin('status', ['inactive']) |
| gt(field, value) | Greater than | .gt('age', 18) |
| gte(field, value) | Greater than or equal | .gte('score', 80) |
| lt(field, value) | Less than | .lt('price', 100) |
| lte(field, value) | Less than or equal | .lte('quantity', 50) |
| between(field, [min, max]) | Between values | .between('age', [18, 65]) |
| isempty(field) | Field is empty | .isempty('description') |
| isnotempty(field) | Field is not empty | .isnotempty('email') |
| exists(field) | Field exists | .exists('phone') |
| notexists(field) | Field does not exist | .notexists('fax') |
| like(field, value) | Like pattern | .like('name', 'John%') |
| ilike(field, value) | Case-insensitive like | .ilike('name', 'john%') |
| notcontains(field, value) | Does not contain | .notcontains('description', 'spam') |
Complex Filtering
// AND conditions
const records = await model.select("name", "email").whereAnd((q) => {
q.gte("age", 18);
q.contains("name", "John");
q.exact("status", "active");
});
// OR conditions
const records = await model.select("name", "email").whereOr((q) => {
q.contains("name", "John");
q.contains("name", "Jane");
});
// Combined AND/OR
const records = await model
.select("name", "email")
.whereAnd((q) => {
q.exact("status", "active");
q.gte("age", 18);
})
.whereOr((q) => {
q.contains("department", "sales");
q.contains("department", "marketing");
});
// Direct filter structure
const records = await model.select("name", "email").filterBy({
and: [
{ field: "status", operator: "eq", value: "active" },
{ field: "age", operator: "gte", value: 18 },
],
});Sorting
// Single field ascending
const records = await model.select("name", "email").orderBy("name");
// Single field descending
const records = await model.select("name", "email").orderBy("-created_at");
// Multiple fields
const records = await model
.select("name", "email")
.orderBy("department", "-created_at", "name");Pagination
// Limit results
const records = await model.select("name", "email").limit(10);
// Page-based pagination
const records = await model.select("name", "email").page(2).limit(10);
// Offset-based pagination
const records = await model.select("name", "email").offset(20).limit(10);Caching Options
// Enable caching for this query
const records = await model
.select("name", "email")
.where({ status: "active" })
.cache();
// Custom TTL for this query
const records = await model
.select("name", "email")
.where({ status: "active" })
.cacheTTL(60 * 60 * 1000); // 1 hour
// Disable cache for this query
const records = await model
.select("name", "email")
.where({ status: "active" })
.noCache();
// Advanced cache options
const records = await model
.select("name", "email")
.where({ status: "active" })
.cacheOptions({
useCache: true,
cacheTTL: 60 * 60 * 1000,
});CRUD Operations
Create
// Create a single record
const record = await model.create({
name: "John Doe",
email: "[email protected]",
status: "active",
});
// Bulk create
const records = await model.bulkCreate(
[
{ name: "John", email: "[email protected]" },
{ name: "Jane", email: "[email protected]" },
],
true,
false
); // ignoreDuplicates=true, enablePartialUpsert=false
// Bulk update (records must have IDs)
const updatedRecords = await model.bulkUpdate(
[
{ id: "record-id-1", name: "Updated John" },
{ id: "record-id-2", email: "[email protected]" },
],
false,
false
); // ignoreDuplicates=false, enablePartialUpsert=falseRead
// Get by ID (deprecated - use select instead)
const record = await model.get("record-id");
// Get or create (deprecated - use select instead)
const result = await model.getOrCreate(
{ email: "[email protected]" },
{ name: "John Doe", status: "active" }
);
console.log(result.record, result.created);Update
// Update by ID
const updated = await model.update("record-id", {
name: "Updated Name",
});
// Update or create (deprecated - use select + update/create instead)
const result = await model.updateOrCreate(
{ email: "[email protected]" },
{ name: "John Doe", status: "active" }
);Delete
// Delete by ID
const deleted = await model.delete("record-id");
// Delete multiple records
const deleted = await model.deleteMany(["id1", "id2", "id3"]);Working with Records
// Get field values
const name = record.get("name");
const email = record.get("email");
// Set field values
record.set("name", "New Name");
record.set("status", "inactive");
// Update record (DEPRECATED - use model.update instead)
const updated = await record.update({
name: "Updated Name",
status: "active",
});
// Delete record
const deleted = await record.delete();
// Refresh from server (deprecated - use model.select instead)
const refreshed = await record.refresh();
// Convert to plain object
const data = record.toJSON();Schema and Field Information
// Get object schema
const schema = await model.getSchema();
// Get all fields
const fields = await model.getFields();
// Get specific field info
const field = await model.getField("fieldSlug");
console.log(field.displayName, field.dataType, field.isRequired);Advanced Caching
// Get cache statistics
const stats = sdk.getCacheStats();
console.log("Hit rate:", stats.hitRate);
console.log("Cache size:", stats.size);
// Clear all cache
sdk.clearCache();
// Invalidate cache for specific object
sdk.invalidateCache("user");
// Clean expired entries
const cleaned = sdk.cleanExpiredCache();
// Enable/disable caching globally
sdk.setCacheEnabled(false);
// Set client credentials
sdk.setClientCredentials("new-client-id", "new-client-secret");Transactional Operations
// Transactional bulk create across multiple objects
const result = await sdk.transactionalBulkCreate(
[
{
object_slug: "user",
record: { name: "John", email: "[email protected]" },
},
{
object_slug: "lead",
record: { name: "Jane", email: "[email protected]" },
},
],
false
); // partialUpsert=false
// Transactional bulk update across multiple objects
const result = await sdk.transactionalBulkUpdate(
[
{ object_slug: "user", record: { id: "user-id", name: "Updated John" } },
{ object_slug: "lead", record: { id: "lead-id", status: "qualified" } },
],
false
); // partialUpsert=false
// Transactional bulk upsert across multiple objects
const result = await sdk.transactionalBulkUpsert(
[
{
object_slug: "user",
record: { name: "John", email: "[email protected]" },
}, // Create
{ object_slug: "lead", record: { id: "lead-id", status: "qualified" } }, // Update
],
false
); // partialUpsert=falseUser Management
// Get current user data
const userData = await sdk.getCurrentUserData();
// Get current user with formatted data
const user = await sdk.getCurrentUser();
console.log(user.user.name, user.orgId, user.timezone);Error Handling
try {
// Query with error handling
const records = await model
.select("name", "email")
.filter("email", "contains", "invalid");
} catch (error) {
console.error("Query failed:", error.message);
}
try {
const record = await model.create({
name: "Test User",
email: "invalid-email",
});
} catch (error) {
console.error("Failed to create record:", error.message);
}TypeScript Support
The SDK includes full TypeScript definitions:
import {
SuperLeapSDK,
createSuperLeapSDK,
Model,
RecordInstance,
DataType,
RelationshipType,
} from "superleap-sdk";
const sdk: SuperLeapSDK = createSuperLeapSDK({
apiKey: "your-api-key",
baseUrl: "https://app.superleap.dev/api/v1",
});
// TypeScript will provide full autocomplete and type checking
const model: Model = sdk.getModel("user");
const records: RecordInstance[] = await model.select("name", "email").cache();
// Use constants
console.log(DataType.Email); // 11
console.log(RelationshipType.OneToMany); // 2Browser Support
The SDK works in all modern browsers and supports:
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Development
Setup for Local Development
Clone the repository
Install dependencies:
yarn installLink the package for local development:
yarn linkIn your consuming project:
yarn link superleap-sdkStart the demo server:
yarn demo
Publishing
# Build and publish to npm
yarn publishExamples
Check out the included index.html file for a complete interactive example with Monaco Editor integration.
API Reference
SuperLeapSDK Class
| Method | Description |
| ---------------------------------- | ------------------------------------ |
| getModel(slug) | Get model instance |
| model(slug) | Alias for getModel |
| setApiKey(key) | Set API key |
| setClientCredentials(id, secret) | Set client credentials |
| request(endpoint, options) | Make raw API request |
| getCurrentUserData() | Get current user data |
| getCurrentUser() | Get formatted current user info |
| getCacheStats() | Get cache statistics |
| clearCache() | Clear all cache |
| invalidateCache(objectSlug) | Invalidate cache for specific object |
| cleanExpiredCache() | Clean expired cache entries |
| setCacheEnabled(enabled) | Enable/disable caching globally |
Model Class
| Method | Description |
| ------------------------------------------------------------ | -------------------------------------- |
| select(...fields) | Get query builder with selected fields |
| selectAll() | Get query builder with all fields |
| create(data) | Create record |
| get(id) | Get record by ID (deprecated) |
| update(id, data) | Update record |
| delete(id) | Delete record |
| deleteMany(ids) | Delete multiple records |
| bulkCreate(records, ignoreDuplicates, enablePartialUpsert) | Bulk create records |
| bulkUpdate(records, ignoreDuplicates, enablePartialUpsert) | Bulk update records |
| getSchema() | Get object schema |
| getFields() | Get all fields |
| getField(fieldSlug) | Get specific field info |
QueryBuilder Class
| Method | Description |
| -------------------------------- | -------------------------------- |
| await queryBuilder | Execute query and return results |
| select(...fields) | Select fields |
| selectAll() | Select all fields |
| where(conditions) | Add WHERE conditions |
| whereAnd(callback) | Add complex AND conditions |
| whereOr(callback) | Add complex OR conditions |
| filter(field, operator, value) | Add filter |
| filterBy(filterObject) | Add complex filter structure |
| exact(field, value) | Exact match filter |
| contains(field, value) | Contains filter |
| gt(field, value) | Greater than filter |
| gte(field, value) | Greater than or equal filter |
| lt(field, value) | Less than filter |
| lte(field, value) | Less than or equal filter |
| in(field, values) | In array filter |
| orderBy(...fields) | Add sorting |
| limit(n) | Limit results |
| page(n) | Set page number |
| offset(n) | Set offset |
| first() | Get first result |
| count() | Get count |
| exists() | Check if records exist |
| cache(options) | Enable caching |
| cacheTTL(ttl) | Set custom cache TTL |
| noCache() | Disable caching |
| cacheOptions(options) | Set advanced cache options |
RecordInstance Class
| Method | Description |
| ------------------- | -------------------------------- |
| get(field) | Get field value |
| set(field, value) | Set field value |
| update(data) | Update record (deprecated) |
| delete() | Delete record |
| refresh() | Refresh from server (deprecated) |
| toJSON() | Convert to plain object |
CacheManager Class
| Method | Description |
| ---------------------- | --------------------- |
| get(key) | Get cached value |
| set(key, value, ttl) | Set cached value |
| delete(key) | Delete cached value |
| clear() | Clear all cache |
| getStats() | Get cache statistics |
| cleanExpired() | Clean expired entries |
DataType Constants
| Constant | Value | Description |
| -------------------------- | ----- | ---------------------- |
| DataType.Int | 1 | Integer |
| DataType.Varchar | 5 | Variable character |
| DataType.Checkbox | 6 | Boolean/Checkbox |
| DataType.DateTime | 7 | Date and time |
| DataType.Date | 8 | Date only |
| DataType.Email | 11 | Email address |
| DataType.Text | 14 | Long text |
| DataType.SingleSelect | 15 | Single select dropdown |
| DataType.MultiSelect | 16 | Multi select dropdown |
| DataType.Url | 17 | URL |
| DataType.FileUpload | 20 | File upload |
| DataType.PhoneNumber | 21 | Phone number |
| DataType.Rating | 22 | Rating field |
| DataType.Decimal | 4 | Decimal number |
| DataType.Currency | 23 | Currency field |
| DataType.Stage | 24 | Stage field |
| DataType.Location | 18 | Location field |
| DataType.Region | 27 | Region field |
| DataType.MultiFileUpload | 29 | Multiple file upload |
RelationshipType Constants
| Constant | Value | Description |
| ----------------------------- | ----- | ------------------------ |
| RelationshipType.OneToOne | 1 | One-to-one relationship |
| RelationshipType.OneToMany | 2 | One-to-many relationship |
| RelationshipType.ManyToOne | 3 | Many-to-one relationship |
| RelationshipType.Restricted | 6 | Restricted relationship |
Migration Guide from v1.x
Breaking Changes
Deprecated Methods: Several methods are now deprecated and will be removed in future versions:
record.update()→ Usemodel.update(id, data)insteadmodel.get()→ Usemodel.select().first()insteadmodel.getOrCreate()→ Usemodel.select().first()+model.create()insteadmodel.updateOrCreate()→ Usemodel.select().first()+model.update()ormodel.create()insteadrecord.refresh()→ Usemodel.select(id)instead
Caching: Caching is now enabled by default with intelligent TTL management
Query Builder: Enhanced with more filter methods and better performance
New Features
- Advanced Caching: Configurable TTL per operation type
- New Filter Methods:
iexact,notexact,notiexact,exists,notexists,like,ilike,notcontains - Complex Filtering:
whereAnd(),whereOr(),filterBy() - Transactional Operations: Cross-object bulk operations
- Schema Management: Lazy-loaded schema with field validation
- Performance Optimizations: Minimal API calls and intelligent cache invalidation
Contributing
- Fork the repository
- Install dependencies:
yarn install - Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the ISC License - see the LICENSE file for details.
Support
For questions and support, please open an issue on GitHub or contact the SuperLeap team.
