Created
June 19, 2015 23:01
-
-
Save bauerca/d5b976516f5189345cb2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Type { | |
constructor() { | |
this.raw = null; | |
this.valid = undefined; | |
} | |
static clone(overrides) { | |
class cloned extends this {}; | |
Object.assign(cloned.prototype, overrides); | |
return cloned; | |
} | |
static named(name) { | |
return this.clone({name}); | |
} | |
static using(overrides) { | |
// maybe pre-process overrides? | |
return this.clone(overrides); | |
} | |
static fromDefaults() { | |
let defaulted = new this(); | |
defaulted.set(defaulted.default); | |
return defaulted; | |
} | |
} | |
Type.prototype.default = null; | |
Type.prototype.optional = false; | |
Type.prototype.validators = []; | |
class AdaptationError extends Error {}; | |
class Scalar extends Type { | |
constructor() { | |
super(); | |
this.value = this.serialized = null; | |
} | |
set(raw) { | |
this.raw = raw; | |
try { | |
this.value = this.adapt(raw); | |
} catch (e) { | |
try { | |
this.serialized = this.serialize(raw); | |
} catch (e) { | |
this.serialized = ''; | |
} | |
this.value = null; | |
return false; | |
} | |
this.serialized = this.serialize(this.value); | |
return true; | |
} | |
validate() { | |
if (this.value === null) { | |
this.valid = this.optional; | |
return this.valid; | |
} | |
this.valid = true; | |
this.validators.reduce((valid, v) => { | |
if (valid) { | |
valid = v.call(this); | |
} | |
return valid; | |
}, this.valid); | |
return this.valid; | |
} | |
} | |
class Str extends Scalar { | |
adapt(raw) { | |
return raw.toString(); | |
} | |
serialize(value) { | |
return value; | |
} | |
} | |
class Int extends Scalar { | |
adapt(raw) { | |
let value = parseInt(raw, 10); | |
if (isNaN(value)) { | |
throw new AdaptationError(`${value} is not a number`); | |
} | |
return value; | |
} | |
serialize(value) { | |
return value.toString(); | |
} | |
} | |
class List extends Type { | |
get value() { | |
return this.members.map(m => m.value); | |
} | |
set(raw) { | |
this.raw = raw; | |
if (!raw.forEach) { | |
return false; | |
} | |
let success = true; | |
this.members = []; | |
let items = []; | |
raw.forEach(mbr => { | |
let member = new this.memberType(); | |
success = success & member.set(mbr); | |
items.push(member); | |
}) | |
if (success) { | |
this.members = items; | |
} | |
} | |
static of(type) { | |
return this.clone({memberType: type}); | |
} | |
} | |
List.prototype.members = []; | |
class Map extends Type { | |
static of(...members) { | |
this.members = members.reduce((ms, m) => { | |
ms[m.name] = m; | |
return ms; | |
}, {}); | |
} | |
} | |
function expect(thing) { | |
return { | |
value: thing, | |
toBe(value) { | |
if (value !== this.value) { | |
console.log(`${this.value} was not ${value}`); | |
//throw new Error(`${this.value} was not ${value}`); | |
} else { | |
//console.log(`${this.value} is ${value}`); | |
} | |
}, | |
toEqual(value) { | |
if (! this.value.every((x, i) => value[i] === x)) { | |
console.log(`${this.value} did not equal ${value}`); | |
} | |
} | |
} | |
} | |
var MyString = Str.named('string').using({default: 'default', optional: false}); | |
var s = new MyString(); | |
expect(s.name).toBe('string'); | |
expect(s.default).toBe('default'); | |
expect(s.optional).toBe(false); | |
// lifecycle | |
expect(s.value).toBe(null); | |
expect(s.valid).toBe(undefined); | |
expect(s.serialized).toBe(null); | |
expect(s.raw).toBe(null); | |
s.validate(); | |
expect(s.valid).toBe(false); | |
s = MyString.fromDefaults(); | |
expect(s.value).toBe(s.default); | |
s.validate(); | |
expect(s.valid).toBe(true); | |
expect(s.set(123)).toBe(true); | |
expect(s.value).toBe('123'); | |
expect(s.raw).toBe(123); | |
expect(s.serialized).toBe('123'); | |
s.validate(); | |
expect(s.valid).toBe(true); | |
let n = new Int(); | |
n.set('yr mom'); | |
expect(n.value).toBe(null) | |
n.set('123'); | |
expect(n.value).toBe(123) | |
var Strings = List.of(Str); | |
let ss = new Strings(); | |
ss.set(['yr', 'mom']); | |
expect(ss.value).toEqual(['yr', 'mom']) | |
var DefaultedStrings = Strings.using({default: ['foo', 'bar']}); | |
let ds = new DefaultedStrings(); | |
expect(ds.value).toEqual([]); | |
let dds = DefaultedStrings.fromDefaults(); | |
expect(ds.value).toEqual(DefaultedStrings.defaults); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment