@instant3p/core-offline
v0.20.12012
Published
Instant's core local abstraction - Offline Fork
Readme
3rd party offline-first fork of Instant's vanilla javascript SDK.
db.subscribeQuery({ todos: {} }, (resp) => {
if (resp.error) {
renderError(resp.error.message);
return;
}
if (resp.data) {
render(resp.data); // wohoo!
}
});Get Started
This is a 3rd party fork providing offline-first capabilities. See the sections below for usage.
Questions?
If you have any questions, feel free to drop us a line on our Discord
An offline-only fork of Instant's core package that pretends to be online while operating entirely offline.
Overview
This package is a minimal fork of Instant's core that makes the following key changes:
- Always reports offline status - Uses
OfflineNetworkListenerinstead ofWindowNetworkListener - Works with cached data - Queries work with locally cached data from IndexedDB
- Enqueues transactions - All transactions are marked as "enqueued" and stored locally
- Improved queryOnce - Returns cached data when offline instead of rejecting
Key Changes Made
1. OfflineNetworkListener.js (New)
// Always reports offline, never attempts WebSocket connections
export default class OfflineNetworkListener {
static async getIsOnline() {
return false; // Always offline
}
static listen(f) {
f(false); // Always report offline
return () => {}; // No-op unsubscribe
}
}2. Modified index.ts
// Uses OfflineNetworkListener by default instead of WindowNetworkListener
import OfflineNetworkListener from './OfflineNetworkListener.js';
// Changed default network listener
NetworkListener || OfflineNetworkListener3. Enhanced Reactor.js
// Enhanced queryOnce to work with cached data when offline
if (!this._isOnline) {
const cachedResult = this.getPreviousResult(q);
if (cachedResult) {
dfd.resolve(cachedResult);
return dfd.promise;
}
}How It Works
- Initialization: Creates a Reactor instance that never attempts WebSocket connections
- Data Storage: All data is stored in IndexedDB like normal InstantDB
- Query Engine: Uses InstantDB's existing query engine with cached data
- Transactions: Transactions are stored locally and marked as "enqueued"
- Relationships: Full support for deep nested relationships using InstantDB's link system
Installation
# Build the package
cd packages/core-offline
npm run buildUsage
Basic Usage
import { init } from '@instant3p/core-offline';
const db = init({
appId: 'your-app-id',
schema: {
entities: {
users: {
id: { type: 'string', unique: true },
name: { type: 'string' },
email: { type: 'string' }
}
}
}
});
// Subscribe to queries (works with cached data)
db.subscribeQuery({ users: {} }, (result) => {
console.log('Users:', result.data);
});
// Transactions (will be enqueued)
await db.transact([
db.tx.users['user-1'].update({
name: 'John Doe',
email: '[email protected]'
})
]);With Relationships
const db = init({
appId: 'your-app-id',
schema: {
entities: {
users: { /* ... */ },
posts: { /* ... */ },
comments: { /* ... */ }
},
links: {
authoredPosts: {
from: { entity: 'users', has: 'many', label: 'posts' },
to: { entity: 'posts', has: 'one', label: 'author' }
},
postComments: {
from: { entity: 'posts', has: 'many', label: 'comments' },
to: { entity: 'comments', has: 'one', label: 'post' }
}
}
}
});
// Deep nested queries work!
db.subscribeQuery({
users: {
posts: {
comments: {
author: {}
}
}
}
}, (result) => {
console.log('Deep nested data:', result.data);
});Testing
Integration Test
A comprehensive integration test suite is included in the __tests__ directory:
# Run all tests
npm test
# Run only integration tests
npm run test:integration
# Run integration tests in watch mode
npm run test:integration:watchThe integration test covers:
- ✅ Connection Status - Verifies offline status
- ✅ Query Subscriptions - Tests deep nested relationship queries
- ✅ Transactions - Tests creating entities and linking them
- ✅ QueryOnce - Tests one-time queries with cached data
- ✅ Data Persistence - Tests data survival across restarts
- ✅ Real Browser Environment - Uses
fake-indexeddbfor IndexedDB simulation
Test Features
- Vitest Framework - Fast, modern test runner
- Browser Environment Simulation - Uses
fake-indexeddbfor realistic testing - Comprehensive Coverage - Tests all major offline functionality
- Automated - Runs in CI/CD pipelines
- Watch Mode - Automatically reruns tests on changes
Differences from Original InstantDB
What Works
- ✅ All query patterns (simple, nested, relationships)
- ✅ Transactions (stored locally)
- ✅ Schema management
- ✅ IndexedDB persistence
- ✅ Subscription system
- ✅ Deep relationship traversal
What's Different
- 🔄 Always offline - Never attempts server connections
- 🔄 Transactions enqueued - All transactions marked as "enqueued"
- 🔄 No real-time sync - Data only exists locally
- 🔄 No auth - Authentication features don't work
- 🔄 No presence - Presence features don't work
- 🔄 No file storage - File upload/download doesn't work
Architecture
This fork maintains InstantDB's core architecture while removing server dependencies:
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────────────────────────────┤
│ @instantdb/core-offline │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│
│ │ Query Engine │ │ Transaction │ │ Link System ││
│ │ │ │ Processing │ │ ││
│ └─────────────────┘ └─────────────────┘ └─────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ Storage Layer │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ IndexedDB │ │ OfflineNetwork │ │
│ │ Storage │ │ Listener │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘Why This Approach?
Instead of reimplementing InstantDB's query engine from scratch, this fork:
- Leverages existing code - Uses 99% of InstantDB's existing functionality
- Minimal changes - Only ~50 lines of code changed
- Maintains compatibility - Same API, same behavior
- Proven query engine - Uses InstantDB's battle-tested query system
- Easy to maintain - Simple to merge updates from upstream
This approach gives you a fully functional offline database with InstantDB's powerful query capabilities while maintaining the exact same API.
