Add Base model type

Mostly copied from gitlab.com/schwalbe-hd/schwalbe

It allows both the names `id` and `uuid` for the identifier field of an instance
This commit is contained in:
Jakob Moser 2025-11-13 00:17:42 +01:00
parent a5c50bd8f9
commit 625a6d72f7
Signed by: jakob
GPG Key ID: 3EF2BA2851B3F53C

View File

@ -0,0 +1,64 @@
function toMap(objs) {
return new Map(objs.map(obj => [obj.id || obj.uuid, obj]))
}
export class Base {
/**
* A Map mapping ids to instances of `Base`.
* Must be treated as private.
*/
static _byId = null
/**
* @return A list of all instances of `Base`
*/
static get all() {
return this._byId ? Array.from(this._byId.values()) : null
}
/**
* @param {str} id A id
* @returns The instance with the given id, if it exists
*/
static get(id) {
return this._byId ? this._byId.get(id) : null
}
/**
* Load the objects from the API, unless the objects have already been loaded.
* They are then stored in `this.byUid`.
*
* @returns Nothing.
*/
static async load() {
if (!this._byId) {
const objects = await this.forceLoad()
// Hack: We get plain JSON objects from the server, however, we'd like
// them to actually be instances of the classes we define. So, we first create a new empty
// instance of whatever subclass of `Base` we are currently in using `new this()`,
// and then copy all properties from the plain object over to the instance
// using `Object.assign`.
const instances = objects.map(obj => Object.assign(new this(), obj))
this._byId = toMap(instances)
}
}
/**
* If the objects were already loaded, forget them and load them again.
* If the objects were not yet loaded, don't do anything.
*/
static refresh() {
if (this._byId) {
this._byId = null
this.load()
}
}
/**
* Load the objects from the API and return them.
* Abstract method, must be overriden in child classes.
*
* @returns A list of instances.
*/
static async forceLoad() {}
}