Skip to content

Commit f127772

Browse files
committed
Refactoring files
1 parent 38b6dfb commit f127772

11 files changed

+529
-467
lines changed

dist/js-data-jsonapi-light.js

+234-167
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js-data-jsonapi-light.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/adapter.ts

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { utils, DataStore, Mapper } from 'js-data';
2+
import { HttpAdapter } from 'js-data-http';
3+
import { Adapter } from 'js-data-adapter';
4+
import { jsonApiDeserialize, wrapDeserialize } from './deserializer';
5+
import { jsonApiSerialize, wrapSerialize } from './serializer';
6+
import { ERROR } from './strings';
7+
8+
export class JsonApiAdapter extends HttpAdapter{
9+
private store: DataStore;
10+
private options: any;
11+
12+
constructor(options?:any) {
13+
options = utils.deepMixIn({
14+
// Some default
15+
}, options || {})
16+
17+
if (!options.store) {
18+
throw new Error(ERROR.FORCE_STORE_OPTION)
19+
}
20+
21+
if (options.serialize || options.deserialize) {
22+
throw new Error(ERROR.PREVENT_SERIALIZE_DESERIALIZE_OPTIONS)
23+
}
24+
25+
super(options);
26+
27+
this.store = options.store;
28+
this.options = options;
29+
30+
this.serialize = wrapSerialize(this);
31+
this.deserialize = wrapDeserialize(this);
32+
}
33+
34+
private warn(...args:any[]) {
35+
console.warn.apply(null, arguments);
36+
return;
37+
}
38+
39+
private handleResponse (opts?:any) { return function (response:any): Promise<any> {
40+
if (opts && opts.raw) {
41+
response.meta = response.data.meta;
42+
response.data = response.data.result;
43+
}
44+
45+
// @todo #6 need to handle errors here
46+
47+
return response;
48+
}}
49+
50+
private handleBeforeLifecycle (opts?:any): Promise<void> {
51+
if(opts && (opts.serialize || opts.deserialize)) {
52+
return Promise.reject(new Error(ERROR.PREVENT_SERIALIZE_DESERIALIZE_OPTIONS))
53+
}
54+
55+
return Promise.resolve();
56+
}
57+
58+
public find(mapper: Mapper, id: string | number, opts?: any): Promise<any> {
59+
return this.handleBeforeLifecycle(opts).then(() => {
60+
return HttpAdapter.prototype.find.call(this, mapper, id, opts);
61+
}).then(this.handleResponse(opts));
62+
}
63+
64+
public findAll(mapper: Mapper, query?: any, opts?: any): Promise<any> {
65+
return this.handleBeforeLifecycle(opts).then(() => {
66+
return HttpAdapter.prototype.findAll.call(this, mapper, query, opts);
67+
}).then(this.handleResponse(opts));
68+
}
69+
70+
public create(mapper: Mapper, props: any, opts?: any): Promise<any> {
71+
return this.handleBeforeLifecycle(opts).then(() => {
72+
return HttpAdapter.prototype.create.call(this, mapper, props, opts);
73+
}).then(this.handleResponse(opts))
74+
}
75+
76+
public createMany(mapper: Mapper, props: any, opts?: any): Promise<any> {
77+
return Promise.reject(new Error('JSONApi doesn\'t support creating in batch.'));
78+
}
79+
80+
public update(mapper: Mapper, id: any, props: any, opts?: any): Promise<any> {
81+
// Ensure id is properly set
82+
props[mapper.idAttribute] = id;
83+
84+
return this.handleBeforeLifecycle(opts).then(() => {
85+
return HttpAdapter.prototype.update.call(this, mapper, id, props, opts)
86+
}).then(this.handleResponse(opts))
87+
}
88+
89+
public updateAll(mapper: Mapper, props: any, query: any, opts?: any): Promise<any> {
90+
return Promise.reject(new Error('JSONApi doesn\'t support updating in batch.'));
91+
}
92+
93+
public updateMany(mapper: Mapper, records: any, opts?: any): Promise<any> {
94+
return Promise.reject(new Error('JSONApi doesn\'t support updating in batch.'));
95+
}
96+
97+
public destroy(mapper: Mapper, id: string | number, opts?: any): Promise<any> {
98+
return this.handleBeforeLifecycle(opts).then(() => {
99+
return HttpAdapter.prototype.destroy.call(this, mapper, id, opts);
100+
}).then(this.handleResponse(opts))
101+
}
102+
103+
public destroyAll(mapper: Mapper, query: any, opts?: any): Promise<any> {
104+
return Promise.reject(new Error('JSONApi doesn\'t support destroying in batch.'));
105+
}
106+
}

src/deserializer.ts

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { mapperCacheRelationByField } from './utils';
2+
import { utils, Mapper } from 'js-data';
3+
4+
export function wrapDeserialize(self:any):any{
5+
return function(mapper:any, res:any, opts:any){
6+
let
7+
beforeDeserialize = opts.beforeDeserialize || mapper.beforeDeserialize || self.options.beforeDeserialize,
8+
afterDeserialize = opts.afterDeserialize || mapper.afterDeserialize || self.options.afterDeserialize;
9+
10+
if (beforeDeserialize) res = beforeDeserialize.call(self, mapper, res, opts);
11+
res = jsonApiDeserialize.call(self, mapper, res, opts);
12+
if (afterDeserialize) res = afterDeserialize.call(self, mapper, res, opts);
13+
return res;
14+
}
15+
}
16+
17+
export function jsonApiDeserialize(mapper:Mapper, res:any, opts:any){
18+
if (!res.data || !res.data.data) return;
19+
20+
const collectionReceived = utils.isArray(res.data.data)
21+
22+
// We store all possible items stores in the response in a Object[type][id]
23+
// structure
24+
let itemsIndexed:any = {};
25+
let itemCollection:Array<any> = [].concat(res.data.included || [])
26+
.concat(res.data.data || []);
27+
28+
let i = itemCollection.length;
29+
while (i--) {
30+
let item:any = itemCollection[i]
31+
if (!item.type || !item.id) {
32+
//@warn
33+
// Just remove it so that we don't need to deal with it later
34+
itemCollection.splice(i, 1);
35+
continue;
36+
}
37+
38+
if (!itemsIndexed[item.type]) itemsIndexed[item.type] = {};
39+
itemsIndexed[item.type][item.id] = item;
40+
}
41+
42+
// Know we will check every possible relationships and try to affect them
43+
// the correct key/id
44+
for (let type in itemsIndexed) {
45+
let resource:any = this.store.getMapper(type);
46+
if (!resource) { this.warn(`Can\'t find resource '${type}'`); continue; }
47+
48+
// Just cache a pointer to relations for the Resource
49+
mapperCacheRelationByField(resource);
50+
51+
for (let id in itemsIndexed[type]) {
52+
let item:any = itemsIndexed[type][id];
53+
item.attributes[resource.idAttribute] = id;
54+
55+
if (!item.relationships || !Object.keys(item.relationships)) continue;
56+
57+
for (let relationField in (item.relationships || {})) {
58+
let relation:any = resource.relationByField[relationField]
59+
if (!relation || !item.relationships[relationField] || !item.relationships[relationField].data) {
60+
continue;
61+
}
62+
63+
if (relation.type === 'belongsTo' || relation.type === 'hasOne') {
64+
let link:any = item.relationships[relationField].data
65+
if (!utils.isObject(link)) {
66+
this.warn('Wrong relation somewhere, object expected', relation);
67+
continue;
68+
}
69+
70+
if (itemsIndexed[link.type] && itemsIndexed[link.type][link.id]) {
71+
let itemLinked:any = itemsIndexed[link.type][link.id];
72+
item.attributes[relation.localField] = itemLinked.attributes;
73+
}
74+
} else if (relation.type === 'hasMany') {
75+
let links:any = item.relationships[relationField].data
76+
if (!utils.isArray(links)) {
77+
this.warn('Wrong relation somewhere, array expected');
78+
continue;
79+
}
80+
81+
item.attributes[relation.localField] = [];
82+
for (let i = 0, l = links.length; i < l; i++) {
83+
let link:any = links[i];
84+
if (itemsIndexed[link.type] && itemsIndexed[link.type][link.id]) {
85+
let itemLinkd:any = itemsIndexed[link.type][link.id];
86+
item.attributes[relation.localField].push(itemLinkd.attributes);
87+
}
88+
}
89+
} else { this.warn('Unknown relation'); continue; }
90+
}
91+
}
92+
}
93+
94+
let outputDatas:Array<any> | any;
95+
if (!collectionReceived) {
96+
outputDatas = res.data.data.attributes;
97+
} else {
98+
outputDatas = [];
99+
for (let i = 0, l = res.data.data.length; i < l; i++) {
100+
outputDatas.push(res.data.data[i].attributes);
101+
}
102+
}
103+
104+
if (!opts.raw) {
105+
return outputDatas;
106+
}
107+
108+
return {
109+
result: outputDatas,
110+
meta: res.data.meta
111+
};
112+
}

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './adapter';

0 commit comments

Comments
 (0)