@lordfokas/magic-orm
Version:
A class-based ORM in TypeScript. Unorthodox and extremely opinionated, made to fit my specific use cases.
76 lines • 2.65 kB
JavaScript
import { Entity } from "./Entity.js";
export class Serializer {
/** Entity name to Entity Class map */
static #forward = {};
/** Entity Class name to Entity name map */
static #reverse = {};
static register(entity, name) {
this.#forward[name] = entity;
this.#reverse[entity.name] = name;
}
/** Transforms a JSON structure into concrete entities */
static fromJSON(data) {
if (typeof data !== 'string')
throw new Error('Expected data type to be string');
return JSON.parse(data, (k, obj) => Serializer.#reviver(obj));
}
/** Transforms an object into concrete entities */
static fromObject(data) {
return Serializer.#traverse(data, (obj) => Serializer.#reviver(obj));
}
/** Deserialization function */
static #reviver(val) {
if (val instanceof Object && val['@type']) {
const obj = val;
const ctor = this.#forward[obj["@type"]];
if (!ctor)
throw new Error(`Entity name "${obj["@type"]}" not recognized`);
const entity = new ctor(obj);
delete entity["@type"];
return entity;
}
else {
return val;
}
}
/** Converts entities into JSON strings. */
static toJSON(data, pretty = false) {
return JSON.stringify(Serializer.toObject(data), null, pretty ? 4 : 0);
}
/** Converts entities into raw objects */
static toObject(data) {
return Serializer.#traverse(data, $ => $, (obj) => {
if (obj instanceof Entity) {
const type = this.#reverse[obj.constructor.name];
if (!type)
throw new Error(`Entity class "${obj.constructor.name}" not recognized`);
return { "@type": type };
}
else if (Array.isArray(data)) {
return [];
}
else {
return obj;
}
});
}
/** Applies a function to every node of the given data */
static #traverse(data, fn, init) {
if (data instanceof Object) {
const obj = init ? init(data) : {};
for (const key in data) {
obj[key] = Serializer.#traverse(data[key], fn, init);
}
return fn(obj);
}
if (Array.isArray(data)) {
const arr = init ? init(data) : [];
for (const e of data) {
arr.push(Serializer.#traverse(e, fn, init));
}
return fn(arr);
}
return data;
}
}
//# sourceMappingURL=Serializer.js.map