frigid ctor
parent
f9cace7815
commit
394e08c55a
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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'
|
||||||
|
|
@ -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)
|
||||||
Reference in New Issue