Skip to content

Commit 9f5d22b

Browse files
author
Lee Richmond
committed
Solidify attributes + classes
1 parent 1572683 commit 9f5d22b

File tree

16 files changed

+313
-31
lines changed

16 files changed

+313
-31
lines changed

example/foo.es6.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// babel example/foo.es6.js -o example/foo.js
22

3-
import { Config, Model } from '../dist/jsorm';
3+
import { Model, attr } from '../dist/jsorm';
44

5-
console.log('exmaple file', Model.baseUrl);
5+
const Person = Model.extend({
6+
myname: attr()
7+
})
8+
9+
let instance = new Person();
10+
instance.myname = 'asdf';
11+
console.log(instance.myname);

example/foo.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22

33
var _jsorm = require('../dist/jsorm');
44

5-
console.log('exmaple file', _jsorm.Model.baseUrl); // babel example/foo.es6.js -o example/foo.js
5+
var Person = _jsorm.Model.extend({
6+
myname: (0, _jsorm.attr)()
7+
}); // babel example/foo.es6.js -o example/foo.js
8+
9+
var instance = new Person();
10+
instance.myname = 'asdf';
11+
console.log(instance.myname);

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ gulp.task('clean:test', function () {
1212

1313
gulp.task('test', ['clean:test'], () =>
1414
gulp
15-
.src(['./index.d.ts.', './src/**/*.ts', './test/test-helper.ts', './test/**/*-test.ts'], { base: '.' })
15+
.src(['./index.d.ts.', './src/**/*.ts', './test/fixtures.ts', './test/test-helper.ts', './test/**/*-test.ts'], { base: '.' })
1616
.pipe(tsProject())
1717
.pipe(gulp.dest('tmp/test'))
1818
.pipe(mocha())

index.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ interface japiDoc {
3232
data: japiResource;
3333
}
3434

35-
interface japiResource {
35+
interface japiResourceIdentifier {
3636
id: string;
3737
type: string;
3838
}
39+
40+
interface japiResource extends japiResourceIdentifier {
41+
attributes?: Object;
42+
relationships?: Object;
43+
meta?: Object;
44+
links?: Object;
45+
}

src/attribute.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// In the future, this class will be used for
2+
// transforms, default values, etc.
3+
4+
import Model from './model';
5+
6+
export default class Attribute {
7+
name: string;
8+
private _value: any;
9+
10+
isAttr: boolean = true;
11+
12+
static applyAll(klass: typeof Model) : void {
13+
this._eachAttribute(klass, (attr) => {
14+
klass.attributeList.push(attr.name);
15+
16+
Object.defineProperty(klass.prototype, attr.name, {
17+
get() : any {
18+
return attr.getter(this);
19+
},
20+
21+
set(value) : void {
22+
attr.setter(this, value);
23+
}
24+
});
25+
});
26+
}
27+
28+
private static _eachAttribute(klass: typeof Model, callback: Function) : void {
29+
let instance = new klass();
30+
for (let propName in instance) {
31+
if (instance[propName] && instance[propName].hasOwnProperty('isAttr')) {
32+
let attrInstance = instance[propName];
33+
attrInstance.name = propName;
34+
callback(attrInstance);
35+
}
36+
}
37+
}
38+
39+
setter(context: Model, val: any) : void {
40+
if (!val.hasOwnProperty('isAttr')) {
41+
context.attributes[this.name] = val;
42+
}
43+
}
44+
45+
getter(context: Model) : any {
46+
return context.attributes[this.name];
47+
}
48+
}

src/configuration.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
/// <reference path="../index.d.ts" />
22

3+
import Model from './model';
4+
import Attribute from './attribute';
5+
36
export default class Config {
4-
static models: Object = {};
7+
static models: Array<typeof Model> = [];
8+
static typeMapping: Object = {};
9+
10+
static bootstrap() : void {
11+
for (let model of this.models) {
12+
this.typeMapping[model.jsonapiType] = model;
13+
Attribute.applyAll(model);
14+
}
15+
}
16+
17+
static reset() : void {
18+
this.typeMapping = {};
19+
this.models = [];
20+
}
21+
22+
static modelForType(type: string) : typeof Model {
23+
return this.typeMapping[type];
24+
}
525
}

src/main.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@ global.__extends = (this && this.__extends) || function (d, b) {
1010

1111
import Config from './configuration';
1212
import Model from './model';
13+
import Attribute from './attribute';
1314

14-
export { Config, Model };
15+
const attr = function() : any {
16+
return new Attribute();
17+
}
18+
19+
export { Config, Model, attr };

src/model.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import Scope from './scope';
44
import Config from './configuration';
5+
import Attribute from './attribute';
6+
import deserialize from './util/deserialize';
7+
import _extend from './util/extend';
58

69
export default class Model implements IModel {
710
static baseUrl = process.env.BROWSER? '': 'http://localhost:9999'
@@ -10,23 +13,30 @@ export default class Model implements IModel {
1013
static jsonapiType = 'define-in-subclass';
1114

1215
id: string;
13-
// attributes
14-
[key: string]: any;
16+
attributes: Object = {};
17+
__meta__: Object | void = null;
18+
parentClass: typeof Model;
19+
klass: typeof Model;
1520

21+
static attributeList = [];
1622
private static _scope: Scope;
1723

18-
static inherited(subclass : typeof Model) {
19-
Config.models[subclass.jsonapiType] = subclass;
24+
static extend(obj : any) : any {
25+
return _extend(this, obj);
26+
}
27+
28+
static inherited(subclass : any) {
29+
Config.models.push(subclass)
30+
subclass.parentClass = this;
31+
subclass.prototype.klass = subclass;
2032
}
2133

2234
static scope(): Scope {
2335
return this._scope || new Scope(this);
2436
}
2537

2638
constructor(attributes?: anyObject) {
27-
for(var key in attributes) {
28-
this[key] = attributes[key];
29-
}
39+
this._assignAttributes(attributes);
3040
}
3141

3242
static all() : Promise<Array<Model>> {
@@ -74,4 +84,16 @@ export default class Model implements IModel {
7484

7585
return base;
7686
}
87+
88+
static fromJsonapi(resource: japiResource) : any {
89+
return deserialize(resource);
90+
}
91+
92+
private _assignAttributes(attrs: Object) : void {
93+
for(var key in attrs) {
94+
if (key == 'id' || this.klass.attributeList.indexOf(key) >= 0) {
95+
this[key] = attrs[key];
96+
}
97+
}
98+
}
7799
}

src/scope.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Model from './model';
22
import Config from './configuration';
3-
import deserialize from './util/deserialize';
43
import parameterize from './util/parameterize';
54
import IncludeDirective from './util/include-directive';
65

@@ -19,14 +18,14 @@ export default class Scope {
1918
all() : Promise<Array<Model>> {
2019
return this._fetch(this.model.url()).then((json : japiDocArray) => {
2120
return json.data.map((datum : japiResource) => {
22-
return deserialize(datum);
21+
return Model.fromJsonapi(datum);
2322
});
2423
});
2524
}
2625

2726
find(id : string | number) : Promise<Model> {
2827
return this._fetch(this.model.url(id)).then((json : japiDoc) => {
29-
return deserialize(json.data);
28+
return Model.fromJsonapi(json.data);
3029
});
3130
}
3231

src/util/deserialize.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
/// <reference path="../../index.d.ts" />
22

33
import Config from '../configuration';
4+
import Model from '../model';
45

5-
export default function deserialize(resource : japiResource) : IModel {
6-
let klass = Config.models[resource.type];
6+
export default function deserialize(resource : japiResource) : Model {
7+
let klass = Config.modelForType(resource.type);
78

89
let instance = new klass({ id: resource.id });
10+
for (let key in resource.attributes) {
11+
instance[key] = resource.attributes[key];
12+
}
13+
instance.__meta__ = resource.meta;
14+
915
return instance;
1016
}

0 commit comments

Comments
 (0)