The future of Avers
Over the last few days I've cleaned up Avers. There was still a bit of code left from the time when I copied parts of the event system of Backbone.js into Avers. The public API has changed slightly, but if you use TypeScript it should be straightforward to see what you need to do.
After finishing that work late at night I was lying in my bed, thinking how to position Avers and where to move next. It works reasonably well for my usecase, but I know of a few features which would make it more appealing to a broader audience.
On JavaScript type systems
A few days ago while reading a discussion on HackerNews I noticed that there is still a group of people who reject the idea of using types (norminal or even just structural) in JavaScript. Which is fine, I'm not judging. But Avers works particularly well when you use it within some form of type system.
If you don't like the idea of using types, you can still use Avers. But you should be prepared to define classes (well, functions) for the different objects which make up the data structures managed by Avers. I think that's a small price to pay for the benefit Avers provides.
More property types
Avers currently supports four property types: primitive (a JavaScript value which Avers doesn't watch, ie. it doesn't emit change events if something within that property changes), object (Avres objects whose changes are tracked), collection (a list of Avers objects) and variant (also called sum type).
It is relatively easy to add new types of properties. For example in a TypeScript project it would be nice to have support for enum properties which are represented as strings in JSON and as TypeScript enums (numbers) at runtime.
I could go even further and allow users to define their own property types. Internally the code is already structured so that it supports arbitrary properties, with the four mentionend earlier being the only ones implemented right now.
Better validation and fatal parse errors
When Avers parses JSON into an object, it initializes properties which are
present in the JSON object and leaves the other properties untouched. You can
optionally normalize the object by using migrateObject. But at no point does
Avers generate a fatal error (ie. throw an exception) if a required property
is not present.
I've tried to design my data structures so that they are always valid and can be migrated forward. Sometimes though a fatal error is a better behavior.
Immutable applyOperation
The current implementation of applyOperation modifies the object in-place.
Certain JavaScript libraries (and people) prefer working with immutable data
structures. I already have an idea how to implement applyOperation so that
it returns a copy of the root object and leaves the original untouched.
One good example where this becomes useful is when you have values which are
functionally dependent on the data represented by Avers objects. If they are
expensive to compute, you want to cache them, but also invalidate when the
objects change. With an immutable applyOperation it becomes very easy to
manage the caches. You simply cache the value on the object instance. Because
applyOperation creates a new instance of the object but only copies the
properties Avers knows about, it'll automatically clear the cache.
Here is an example how it would loook in practice. The book has a property
wordCount which needs to be updated everytime something in the book (in
particular in the pages) changes.
class Page {
text : string;
}
class Book {
pages : Avers.Collection<Page>;
private _wordCount = undefined;
get wordCount() {
if (this._wordCount === undefined) {
this._wordCount = this.pages.reduce((a, page) => {
return //...
}, 0);
}
return this._wordCount;
}
}
Synthetic change records
Avers generates two types of change records: set and splice. These map directly to the change records generated by the underlying Object.observe mechanism. If you want to use Avers in the context of an OT framework, it might be desireable to be able to emit your own types of change records. ShareJS for example supports many more operations.