When encoding or decoding data, you must specify a version number. This versioning system allows making changes to the data structure while maintaining compatibility with stored data and older clients.
AutoEncoder (Writing AutoEncoder classes) has an easy way to introduce new fields or make changes to fields using the @field decorator.
Let's say you want to change the ID field from a number to a string type, and add a new field called createdAt. Versioning makes this possible:
class MyClass extends AutoEncoder {
@field({ decoder: NumberDecoder })
@field({
decoder: StringDecoder,
version: 2,
upgrade: (old: number) => old.toString(),
downgrade: (n: string) => parseInt(n)
})
id: number;
@field({ decoder: StringDecoder })
name: string;
@field({ decoder: MyClass, nullable: true })
other: MyClass | null = null;
@field({ decoder: DateDecoder, version: 2, upgrade: () => new Date() })
createdAt: Date;
}
For other classes you'll have to implement it manually in your encode/decode methods (Manually implementing encode and decode).
Version constantIn Stamhoofd, we store the current version in Version (shared/structures/src/Version.ts).
Encoding
import { Version } from "@stamhoofd/structures";
const pablo = Dog.create({ id: "123", name: "Pablo", createdAt: new Date() });
const json = JSON.stringify(pablo.encode({ version: Version }));
// Do something with json (send it over the network, store it...)
Decoding
import { Version } from "@stamhoofd/structures";
const plainObject = JSON.parse(json);
const data = new ObjectData(plainObject, { version: Version });
const pablo = Dog.decode(data);
Increasing the version
We increase the version only during Stamhoofd releases to avoid conflicts when multiple people make changes simultaneously or switch between branches. For adding new properties to data structures during development, use the ...NextVersion helper.