diff --git a/package.json b/package.json index 24f55e3c..573b1e91 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@angular/platform-browser-dynamic": "2.2.3", "@angular/platform-server": "2.2.3", "@types/jasmine": "2.5.38", - "@types/lodash": "^4.14.37", + "@types/lodash": "4.14.37", "@types/reflect-metadata": "0.0.4", "@types/selenium-webdriver": "^2.53.30", "codelyzer": "~2.0.0-beta.1", diff --git a/src/index.ts b/src/index.ts index 28ac2698..46dd03a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,9 +5,11 @@ export * from './decorators/json-api-model-config.decorator'; export * from './decorators/json-api-datastore-config.decorator'; export * from './models/json-api.model'; +export * from './models/document.model'; +export * from './models/links.model'; +export * from './models/link.model'; export * from './models/error-response.model'; export * from './providers'; export * from './module'; - diff --git a/src/models/document.model.ts b/src/models/document.model.ts new file mode 100644 index 00000000..1fe3eb80 --- /dev/null +++ b/src/models/document.model.ts @@ -0,0 +1,22 @@ +import { LinksModel } from './links.model'; + +export class DocumentModel { + private _links: LinksModel = new LinksModel; + private _data: T; + + constructor(body: any) { + this._links.updateLinks(body.links); + } + + get links() { + return this._links; + } + + get data(): T { + return this._data; + } + + set data(data: T) { + this._data = data; + } +} diff --git a/src/models/json-api.model.ts b/src/models/json-api.model.ts index 042b2927..2e25fe00 100644 --- a/src/models/json-api.model.ts +++ b/src/models/json-api.model.ts @@ -2,10 +2,14 @@ import * as _ from 'lodash'; import { Headers } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { JsonApiDatastore, ModelType } from '../services/json-api-datastore.service'; +import { LinksModel } from './links.model'; +import { LinkModel } from './link.model'; +import { DocumentModel } from '../models/document.model'; export class JsonApiModel { id: string; + private _links: LinksModel = new LinksModel; [key: string]: any; constructor(private _datastore: JsonApiDatastore, data?: any) { @@ -13,6 +17,11 @@ export class JsonApiModel { this.id = data.id; _.extend(this, data.attributes); } + this._links.updateLinks(data.links); + } + + get links() { + return this._links; } syncRelationships(data: any, included: any, level: number): void { @@ -22,7 +31,7 @@ export class JsonApiModel { } } - save(params?: any, headers?: Headers): Observable { + save(params?: any, headers?: Headers): Observable> { let attributesMetadata: any = Reflect.getMetadata('Attribute', this); return this._datastore.saveRecord(attributesMetadata, this, params, headers); } diff --git a/src/models/link.model.ts b/src/models/link.model.ts new file mode 100644 index 00000000..c4b10fa0 --- /dev/null +++ b/src/models/link.model.ts @@ -0,0 +1,18 @@ +export class LinkModel { + private _name: string; + private _href: string; + // TODO: add meta + + constructor(name: string, link: any) { + this._name = name; + this._href = link; + } + + get name(): string { + return this._name; + } + + get href(): string { + return this._href; + } +} diff --git a/src/models/links.model.ts b/src/models/links.model.ts new file mode 100644 index 00000000..e48d0f73 --- /dev/null +++ b/src/models/links.model.ts @@ -0,0 +1,17 @@ +import { LinkModel } from './link.model'; + +export class LinksModel { + [key: string]: any; + + public updateLinks(links: any) { + // delete all properties of this object + Object.keys(this || {}).forEach((name) => { + delete this[name]; + }); + + // assign new properties based on whats inside of links + Object.keys(links || {}).forEach((name) => { + this[name] = new LinkModel(name, links[name]); + }); + } +} diff --git a/src/services/json-api-datastore.service.ts b/src/services/json-api-datastore.service.ts index 1bfb85fe..66318ced 100644 --- a/src/services/json-api-datastore.service.ts +++ b/src/services/json-api-datastore.service.ts @@ -7,9 +7,15 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/throw'; import { JsonApiModel } from '../models/json-api.model'; +import { DocumentModel } from '../models/document.model'; import {ErrorResponse} from '../models/error-response.model'; -export type ModelType = { new(datastore: JsonApiDatastore, data: any): T; }; +export type ModelType = { + new( + datastore: JsonApiDatastore, + data: any + ): T; +}; @Injectable() export class JsonApiDatastore { @@ -20,7 +26,7 @@ export class JsonApiDatastore { constructor(private http: Http) { } - query(modelType: ModelType, params?: any, headers?: Headers): Observable { + query(modelType: ModelType, params?: any, headers?: Headers): Observable> { let options: RequestOptions = this.getOptions(headers); let url: string = this.buildUrl(modelType, params); return this.http.get(url, options) @@ -28,7 +34,7 @@ export class JsonApiDatastore { .catch((res: any) => this.handleError(res)); } - findRecord(modelType: ModelType, id: string, params?: any, headers?: Headers): Observable { + findRecord(modelType: ModelType, id: string, params?: any, headers?: Headers): Observable> { let options: RequestOptions = this.getOptions(headers); let url: string = this.buildUrl(modelType, params, id); return this.http.get(url, options) @@ -40,7 +46,7 @@ export class JsonApiDatastore { return new modelType(this, {attributes: data}); } - saveRecord(attributesMetadata: any, model?: T, params?: any, headers?: Headers): Observable { + saveRecord(attributesMetadata: any, model?: T, params?: any, headers?: Headers): Observable> { let modelType = >model.constructor; let typeName: string = Reflect.getMetadata('JsonApiModelConfig', modelType).type; let options: RequestOptions = this.getOptions(headers); @@ -123,9 +129,10 @@ export class JsonApiDatastore { return relationships; } - private extractQueryData(res: any, modelType: ModelType): T[] { + private extractQueryData(res: any, modelType: ModelType): DocumentModel { let body: any = res.json(); let models: T[] = []; + let document: DocumentModel = new DocumentModel(body); body.data.forEach((data: any) => { let model: T = new modelType(this, data); this.addToStore(model); @@ -135,11 +142,13 @@ export class JsonApiDatastore { } models.push(model); }); - return models; + document.data = models; + return document; } - private extractRecordData(res: any, modelType: ModelType, model?: T): T { + private extractRecordData(res: any, modelType: ModelType, model?: T): DocumentModel { let body: any = res.json(); + let document: DocumentModel = new DocumentModel(body); if (model) { model.id = body.data.id; _.extend(model, body.data.attributes); @@ -150,7 +159,8 @@ export class JsonApiDatastore { model.syncRelationships(body.data, body.included, 0); this.addToStore(model); } - return model; + document.data = model; + return document; } protected handleError(error: any): ErrorObservable {