frigid ctor
parent
f9cace7815
commit
394e08c55a
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "frigid",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"main": "out/index.js",
|
||||
"types": "out/index.d.ts",
|
||||
"license": "MIT",
|
||||
|
|
|
|||
|
|
@ -2,30 +2,28 @@ import { existsSync, readFileSync, writeFileSync } from "fs";
|
|||
import Serializable from "./Serializable.js";
|
||||
|
||||
const PERSIST_LOCATION = Symbol('PERSIST_LOCATION');
|
||||
export const RESTORE = Symbol('RESTORE');
|
||||
|
||||
export default class Frigid extends Serializable {
|
||||
|
||||
ctor() {}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static create(filename: string, ...args: any[]) {
|
||||
if(existsSync(filename)) {
|
||||
const instance = new this(...args);
|
||||
const instanceStuff = this.deserialize(readFileSync(filename));
|
||||
for(const key of Object.keys(instanceStuff)) {
|
||||
instance[key] = instanceStuff[key]
|
||||
|
||||
const instance = (() => {
|
||||
if(existsSync(filename)) {
|
||||
return this.deserialize(readFileSync(filename));
|
||||
} else {
|
||||
return new this(...args);
|
||||
}
|
||||
// TS is plain and simply wrong... symbols can be used to index object...
|
||||
// @ts-ignore
|
||||
instance[PERSIST_LOCATION] = filename;
|
||||
instance[RESTORE]?.();
|
||||
return instance;
|
||||
} else {
|
||||
const instance = new this(...args);
|
||||
// again... TS is wrong...
|
||||
// @ts-ignore
|
||||
instance[PERSIST_LOCATION] = filename;
|
||||
instance[RESTORE]?.();
|
||||
instance.sync();
|
||||
return instance;
|
||||
}
|
||||
})();
|
||||
|
||||
finalze(instance, filename);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
sync() {
|
||||
|
|
@ -34,4 +32,29 @@ export default class Frigid extends Serializable {
|
|||
// @ts-ignore
|
||||
writeFileSync(this[PERSIST_LOCATION], data);
|
||||
}
|
||||
}
|
||||
|
||||
function walk(obj, transform) {
|
||||
if(obj instanceof Serializable) {
|
||||
transform(obj);
|
||||
}
|
||||
for(const key of Object.keys(obj)) {
|
||||
const val = obj[key];
|
||||
if(typeof obj === 'object') {
|
||||
walk(val, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finalze(instance, filename) {
|
||||
// TS is plain and simply wrong... symbols can be used to index object...
|
||||
// @ts-ignore
|
||||
instance[PERSIST_LOCATION] = filename;
|
||||
|
||||
walk(instance, (obj) => {
|
||||
// console.log(obj instanceof Serializable)
|
||||
(obj as any).ctor?.();
|
||||
});
|
||||
|
||||
instance.sync();
|
||||
}
|
||||
|
|
@ -4,7 +4,9 @@ import { reverseLookup } from './reverseLookup.js';
|
|||
|
||||
export default class Serializable {
|
||||
|
||||
constructor(...args: any[]) {}
|
||||
// takes as many args as it needs to (so subclasses can
|
||||
// define their own constructor, with any number of args)
|
||||
constructor(...args) {}
|
||||
|
||||
// things that need to be stored only in cold
|
||||
// storage are keyed with a special prefix
|
||||
|
|
@ -23,8 +25,8 @@ export default class Serializable {
|
|||
return JSON.stringify(this.toSerializableObject(), null, 2);
|
||||
}
|
||||
|
||||
static fromJson(str: string) {
|
||||
return this.fromSerializableObject(JSON.parse(str));
|
||||
static fromJson(str: string, instances: Map<number, object> = new Map()) {
|
||||
return this.fromSerializableObject(JSON.parse(str), instances);
|
||||
}
|
||||
|
||||
// this doesnt operate recursively, it doesnt need to, because
|
||||
|
|
@ -180,17 +182,7 @@ export default class Serializable {
|
|||
|
||||
}
|
||||
|
||||
static deserialize(obj: any, {
|
||||
encoding = 'json'
|
||||
} = {}) {
|
||||
|
||||
switch(encoding) {
|
||||
case 'json': return this.fromJson(obj);
|
||||
case 'ubjson':
|
||||
// case 'ubj': return this.fromUbj(obj);
|
||||
default: {
|
||||
throw new TypeError('Unknown encoding: ' + encoding);
|
||||
}
|
||||
}
|
||||
static deserialize(obj: any, instances: Map<number, object> = new Map()) {
|
||||
return this.fromJson(obj, instances);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
export {default as Serializable} from './Serializable.js';
|
||||
export {default as Frigid, RESTORE} from './Frigid.js'
|
||||
export {default as Frigid} from './Frigid.js'
|
||||
|
|
@ -1,24 +1,35 @@
|
|||
import {Frigid, RESTORE} from '../out/index.js';
|
||||
import { Frigid, Serializable } from '../out/index.js';
|
||||
import { existsSync, readFileSync, unlinkSync } from 'fs';
|
||||
import { expect } from 'chai';
|
||||
|
||||
const trackingData = {
|
||||
constructorCalls: 0,
|
||||
restoreCalls: 0
|
||||
ctor: 0,
|
||||
subCtor: 0
|
||||
}
|
||||
|
||||
class Sub extends Serializable {
|
||||
ctor() {
|
||||
trackingData.subCtor ++;
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Frigid {
|
||||
foo = 'bar';
|
||||
|
||||
test = new Sub();
|
||||
|
||||
static serializationDependencies() {
|
||||
return [ Sub ];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
trackingData.constructorCalls ++;
|
||||
console.log('construct')
|
||||
}
|
||||
|
||||
[RESTORE]() {
|
||||
trackingData.restoreCalls ++;
|
||||
console.log('restore')
|
||||
ctor() {
|
||||
trackingData.ctor ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,11 +47,13 @@ expect(existsSync(filepath)).to.be.true;
|
|||
expect(readFileSync(filepath).toString()).to.not.be.empty;
|
||||
|
||||
expect(trackingData.constructorCalls).to.equal(1);
|
||||
expect(trackingData.restoreCalls).to.equal(1);
|
||||
expect(trackingData.subCtor).to.equal(1);
|
||||
expect(trackingData.ctor).to.equal(1);
|
||||
|
||||
const retest = Test.create(filepath);
|
||||
|
||||
expect(trackingData.constructorCalls).to.equal(2);
|
||||
expect(trackingData.restoreCalls).to.equal(2);
|
||||
expect(trackingData.constructorCalls).to.equal(1);
|
||||
expect(trackingData.subCtor).to.equal(2);
|
||||
expect(trackingData.ctor).to.equal(2);
|
||||
|
||||
unlinkSync(filepath)
|
||||
Reference in New Issue