Features:
- New binary protocol support (under the hood)
- Bulk actions support (under the hood)
- Full typescript declaration files
- Promises everywhere! Long live async/await!
- Offline record support
{
// Use indexdb to store data client side
offlineEnabled: false,
// Save each update as it comes in from the server
saveUpdatesOffline: false,
indexdb: {
// The db version, incrementing this triggers a db upgrade
dbVersion: 1,
// This auto updates the indexdb version if the objectStore names change
autoVersion: false,
// The key to index records by
primaryKey: 'id',
// The indexdb databae name
storageDatabaseName: 'deepstream',
// The default store name if not using a '/' to indicate the object store (example person/uuid)
defaultObjectStoreName: 'records',
// The object store names, required in advance due to how indexdb works
objectStoreNames: [],
// Things to not save, such search results
ignorePrefixes: [],
// The amount of time to buffer together actions before making a request
flushTimeout: 50
}
}
- Customizable offline storage support
export type offlineStoreWriteResponse = ((error: string | null, recordName: string) => void)
export interface RecordOfflineStore {
get: (recordName: string, callback: ((recordName: string, version: number, data: RecordData) => void)) => void
set: (recordName: string, version: number, data: RecordData, callback: offlineStoreWriteResponse) => void
delete: (recordName: string, callback: offlineStoreWriteResponse) => void
}
Improvements
- Separation of errors and warnings for clarity. Non critical failures (such as an ack timeout) can now be treated separated or fully muted.
- Enhanced services to reduce timeout overhead
Backwards compatibility
- Only works with V4 server
- All single response APIs now return promises when not providing a callback. This means most APIs that could have been chained would now break.
const client = deepstream()
try {
await client.login()
const record = client.record.getRecord(name)
await record.whenReady()
const data = await client.record.snapshot(name)
const version = await client.record.head(name)
const exists = await client.record.has(name)
const result = await client.rpc.make(name, data)
const users = await client.presence.getAll()
} catch (e) {
console.log('Error occurred', e)
}
- Listening
The listening API has been ever so slightly tweaked in order to simplify removing an active subscription.
Before when an active provider was started you would usually need to store it in a higher scope, for example:
const listeners = new Map()
client.record.listen('users/.*', (name, isSubscribed, ({ accept, reject }) => {
if (isSubscribed) {
const updateInterval = setInterval(updateRecord.bind(this, name), 1000)
listeners.set(name, updateInterval)
accept()
} else {
clearTimeout(listeners.get(name))
listeners.delete(name)
}
})
Where now we instead do:
const listeners = new Map()
client.record.listen('users/.*', (name, ({ accept, reject, onStop }) => {
const updateInterval = setInterval(updateRecord.bind(this, name), 1000)
accept()
onStop(() => clearTimeout(updateInterval))
})
TLDR;
You can see the in depth side explanation of the changes here