frigid ctor

master
Valerie 2021-06-12 15:11:53 -04:00
parent f9cace7815
commit 394e08c55a
5 changed files with 74 additions and 46 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "frigid", "name": "frigid",
"version": "1.2.0", "version": "1.3.0",
"main": "out/index.js", "main": "out/index.js",
"types": "out/index.d.ts", "types": "out/index.d.ts",
"license": "MIT", "license": "MIT",

View File

@ -2,30 +2,28 @@ import { existsSync, readFileSync, writeFileSync } from "fs";
import Serializable from "./Serializable.js"; import Serializable from "./Serializable.js";
const PERSIST_LOCATION = Symbol('PERSIST_LOCATION'); const PERSIST_LOCATION = Symbol('PERSIST_LOCATION');
export const RESTORE = Symbol('RESTORE');
export default class Frigid extends Serializable { export default class Frigid extends Serializable {
ctor() {}
constructor(...args) {
super(...args);
}
static create(filename: string, ...args: any[]) { static create(filename: string, ...args: any[]) {
const instance = (() => {
if(existsSync(filename)) { if(existsSync(filename)) {
const instance = new this(...args); return this.deserialize(readFileSync(filename));
const instanceStuff = this.deserialize(readFileSync(filename));
for(const key of Object.keys(instanceStuff)) {
instance[key] = instanceStuff[key]
}
// TS is plain and simply wrong... symbols can be used to index object...
// @ts-ignore
instance[PERSIST_LOCATION] = filename;
instance[RESTORE]?.();
return instance;
} else { } else {
const instance = new this(...args); return 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() { sync() {
@ -35,3 +33,28 @@ export default class Frigid extends Serializable {
writeFileSync(this[PERSIST_LOCATION], data); 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();
}

View File

@ -4,7 +4,9 @@ import { reverseLookup } from './reverseLookup.js';
export default class Serializable { 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 // things that need to be stored only in cold
// storage are keyed with a special prefix // storage are keyed with a special prefix
@ -23,8 +25,8 @@ export default class Serializable {
return JSON.stringify(this.toSerializableObject(), null, 2); return JSON.stringify(this.toSerializableObject(), null, 2);
} }
static fromJson(str: string) { static fromJson(str: string, instances: Map<number, object> = new Map()) {
return this.fromSerializableObject(JSON.parse(str)); return this.fromSerializableObject(JSON.parse(str), instances);
} }
// this doesnt operate recursively, it doesnt need to, because // this doesnt operate recursively, it doesnt need to, because
@ -180,17 +182,7 @@ export default class Serializable {
} }
static deserialize(obj: any, { static deserialize(obj: any, instances: Map<number, object> = new Map()) {
encoding = 'json' return this.fromJson(obj, instances);
} = {}) {
switch(encoding) {
case 'json': return this.fromJson(obj);
case 'ubjson':
// case 'ubj': return this.fromUbj(obj);
default: {
throw new TypeError('Unknown encoding: ' + encoding);
}
}
} }
} }

View File

@ -1,2 +1,2 @@
export {default as Serializable} from './Serializable.js'; export {default as Serializable} from './Serializable.js';
export {default as Frigid, RESTORE} from './Frigid.js' export {default as Frigid} from './Frigid.js'

View File

@ -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 { existsSync, readFileSync, unlinkSync } from 'fs';
import { expect } from 'chai'; import { expect } from 'chai';
const trackingData = { const trackingData = {
constructorCalls: 0, constructorCalls: 0,
restoreCalls: 0 ctor: 0,
subCtor: 0
}
class Sub extends Serializable {
ctor() {
trackingData.subCtor ++;
}
} }
class Test extends Frigid { class Test extends Frigid {
foo = 'bar'; foo = 'bar';
test = new Sub();
static serializationDependencies() {
return [ Sub ];
}
constructor() { constructor() {
super(); super();
trackingData.constructorCalls ++; trackingData.constructorCalls ++;
console.log('construct')
} }
[RESTORE]() { ctor() {
trackingData.restoreCalls ++; trackingData.ctor ++;
console.log('restore')
} }
} }
@ -36,11 +47,13 @@ expect(existsSync(filepath)).to.be.true;
expect(readFileSync(filepath).toString()).to.not.be.empty; expect(readFileSync(filepath).toString()).to.not.be.empty;
expect(trackingData.constructorCalls).to.equal(1); 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); const retest = Test.create(filepath);
expect(trackingData.constructorCalls).to.equal(2); expect(trackingData.constructorCalls).to.equal(1);
expect(trackingData.restoreCalls).to.equal(2); expect(trackingData.subCtor).to.equal(2);
expect(trackingData.ctor).to.equal(2);
unlinkSync(filepath) unlinkSync(filepath)