From 2dbc30c35abe078d80b11b879c3fdd54fd1f0737 Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sun, 18 Feb 2018 10:55:45 +0100 Subject: [PATCH 1/6] Rename JsonApiQueryData to JsonApiDocument to clarify purpose and match naming in jsonapi specification. Signed-off-by: Clemens John --- README.MD | 2 +- src/index.ts | 2 +- .../{json-api-query-data.ts => json-api-document.ts} | 2 +- src/services/json-api-datastore.service.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/models/{json-api-query-data.ts => json-api-document.ts} (85%) diff --git a/README.MD b/README.MD index 06900cf7..2b6b49b1 100644 --- a/README.MD +++ b/README.MD @@ -190,7 +190,7 @@ getPosts(){ title: 'My Post', }, }).subscribe( - (posts: JsonApiQueryData) => console.log(posts.getModels()) + (posts: JsonApiCollection) => console.log(posts.getModels()) ); } ``` diff --git a/src/index.ts b/src/index.ts index dfd03c62..87cd05f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ export * from './decorators/json-api-datastore-config.decorator'; export * from './models/json-api-meta.model'; export * from './models/json-api.model'; export * from './models/error-response.model'; -export * from './models/json-api-query-data'; +export * from './models/json-api-document'; export * from './interfaces/overrides.interface'; export * from './interfaces/datastore-config.interface'; diff --git a/src/models/json-api-query-data.ts b/src/models/json-api-document.ts similarity index 85% rename from src/models/json-api-query-data.ts rename to src/models/json-api-document.ts index 3ecee737..53dd042e 100644 --- a/src/models/json-api-query-data.ts +++ b/src/models/json-api-document.ts @@ -1,4 +1,4 @@ -export class JsonApiQueryData { +export class JsonApiDocument { constructor(protected jsonApiModels: Array, protected metaData?: any) {} public getModels(): T[] { diff --git a/src/services/json-api-datastore.service.ts b/src/services/json-api-datastore.service.ts index 6cb98855..66f5faf8 100644 --- a/src/services/json-api-datastore.service.ts +++ b/src/services/json-api-datastore.service.ts @@ -9,7 +9,7 @@ import 'rxjs/add/observable/throw'; import 'rxjs/add/observable/of'; import { JsonApiModel } from '../models/json-api.model'; import { ErrorResponse } from '../models/error-response.model'; -import { JsonApiQueryData } from '../models/json-api-query-data'; +import { JsonApiDocument } from '../models/json-api-document'; import * as qs from 'qs'; import { DatastoreConfig } from '../interfaces/datastore-config.interface'; import { ModelConfig } from '../interfaces/model-config.interface'; @@ -60,7 +60,7 @@ export class JsonApiDatastore { params?: any, headers?: Headers, customUrl?: string - ): Observable> { + ): Observable> { const options: RequestOptions = this.getOptions(headers); const url: string = this.buildUrl(modelType, params, undefined, customUrl); @@ -254,7 +254,7 @@ export class JsonApiDatastore { res: any, modelType: ModelType, withMeta = false - ): T[] | JsonApiQueryData { + ): T[] | JsonApiDocument { const body: any = res.json(); const models: T[] = []; @@ -271,7 +271,7 @@ export class JsonApiDatastore { }); if (withMeta && withMeta === true) { - return new JsonApiQueryData(models, this.parseMeta(body, modelType)); + return new JsonApiDocument(models, this.parseMeta(body, modelType)); } return models; } From d827ddff9135ada477871812ad6856f51e25d52f Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sun, 18 Feb 2018 11:27:00 +0100 Subject: [PATCH 2/6] Allow passing a single Object to JsonApiDocument and add Method getModel() for retrieving it. Signed-off-by: Clemens John --- src/models/json-api-document.ts | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/models/json-api-document.ts b/src/models/json-api-document.ts index 53dd042e..83abe89e 100644 --- a/src/models/json-api-document.ts +++ b/src/models/json-api-document.ts @@ -1,11 +1,27 @@ export class JsonApiDocument { - constructor(protected jsonApiModels: Array, protected metaData?: any) {} + constructor(protected data: Array | T, protected meta?: any) {} - public getModels(): T[] { - return this.jsonApiModels; + public getModels() : T[] { + if (!(this.data instanceof Array)) { + throw new Error('Data is not an array.'); + } + + return this.data; + } + + public getModel() : T { + if (this.data instanceof Array) { + throw new Error('Data is not an object.'); + } + + return this.data; + } + + public getData(): T[] | T { + return this.data; } public getMeta(): any { - return this.metaData; + return this.meta; } } From e2c59c6a21725579cc9359a83c4bae97247a53a4 Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sun, 18 Feb 2018 11:31:23 +0100 Subject: [PATCH 3/6] Revert "Rename JsonApiQueryData to JsonApiDocument to clarify purpose and match naming in jsonapi specification." This reverts commit 2dbc30c35abe078d80b11b879c3fdd54fd1f0737. --- README.MD | 2 +- src/index.ts | 2 +- .../{json-api-document.ts => json-api-query-data.ts} | 2 +- src/services/json-api-datastore.service.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/models/{json-api-document.ts => json-api-query-data.ts} (93%) diff --git a/README.MD b/README.MD index 2b6b49b1..06900cf7 100644 --- a/README.MD +++ b/README.MD @@ -190,7 +190,7 @@ getPosts(){ title: 'My Post', }, }).subscribe( - (posts: JsonApiCollection) => console.log(posts.getModels()) + (posts: JsonApiQueryData) => console.log(posts.getModels()) ); } ``` diff --git a/src/index.ts b/src/index.ts index 87cd05f8..dfd03c62 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ export * from './decorators/json-api-datastore-config.decorator'; export * from './models/json-api-meta.model'; export * from './models/json-api.model'; export * from './models/error-response.model'; -export * from './models/json-api-document'; +export * from './models/json-api-query-data'; export * from './interfaces/overrides.interface'; export * from './interfaces/datastore-config.interface'; diff --git a/src/models/json-api-document.ts b/src/models/json-api-query-data.ts similarity index 93% rename from src/models/json-api-document.ts rename to src/models/json-api-query-data.ts index 83abe89e..dfb222f5 100644 --- a/src/models/json-api-document.ts +++ b/src/models/json-api-query-data.ts @@ -1,4 +1,4 @@ -export class JsonApiDocument { +export class JsonApiQueryData { constructor(protected data: Array | T, protected meta?: any) {} public getModels() : T[] { diff --git a/src/services/json-api-datastore.service.ts b/src/services/json-api-datastore.service.ts index 66f5faf8..6cb98855 100644 --- a/src/services/json-api-datastore.service.ts +++ b/src/services/json-api-datastore.service.ts @@ -9,7 +9,7 @@ import 'rxjs/add/observable/throw'; import 'rxjs/add/observable/of'; import { JsonApiModel } from '../models/json-api.model'; import { ErrorResponse } from '../models/error-response.model'; -import { JsonApiDocument } from '../models/json-api-document'; +import { JsonApiQueryData } from '../models/json-api-query-data'; import * as qs from 'qs'; import { DatastoreConfig } from '../interfaces/datastore-config.interface'; import { ModelConfig } from '../interfaces/model-config.interface'; @@ -60,7 +60,7 @@ export class JsonApiDatastore { params?: any, headers?: Headers, customUrl?: string - ): Observable> { + ): Observable> { const options: RequestOptions = this.getOptions(headers); const url: string = this.buildUrl(modelType, params, undefined, customUrl); @@ -254,7 +254,7 @@ export class JsonApiDatastore { res: any, modelType: ModelType, withMeta = false - ): T[] | JsonApiDocument { + ): T[] | JsonApiQueryData { const body: any = res.json(); const models: T[] = []; @@ -271,7 +271,7 @@ export class JsonApiDatastore { }); if (withMeta && withMeta === true) { - return new JsonApiDocument(models, this.parseMeta(body, modelType)); + return new JsonApiQueryData(models, this.parseMeta(body, modelType)); } return models; } From 08580a6e4d9f2ee2818bc11f39e389f81e8898e4 Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sun, 18 Feb 2018 12:06:52 +0100 Subject: [PATCH 4/6] Add findOne method which returns a JsonApiQueryData object. Add testcase. Signed-off-by: Clemens John --- .../json-api-datastore.service.spec.ts | 24 ++++++++++++++ src/services/json-api-datastore.service.ts | 32 +++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/services/json-api-datastore.service.spec.ts b/src/services/json-api-datastore.service.spec.ts index 7ec1cd00..a350c00b 100644 --- a/src/services/json-api-datastore.service.spec.ts +++ b/src/services/json-api-datastore.service.spec.ts @@ -294,6 +294,30 @@ describe('JsonApiDatastore', () => { }); }); + it('should get author with custom metadata', () => { + backend.connections.subscribe((c: MockConnection) => { + c.mockRespond(new Response( + new ResponseOptions({ + body: JSON.stringify({ + data: getAuthorData(), + meta: { + dates: { + generatedAt: 1518950882 + } + } + }) + }) + )); + }); + + datastore.findOne(Author, '1').subscribe((document) => { + expect(document.getModel()).toBeDefined(); + expect(document.getModel().id).toBe(AUTHOR_ID); + expect(document.getModel().date_of_birth).toEqual(parse(AUTHOR_BIRTH)); + expect(document.getMeta().meta.dates.generatedAt).toEqual(1518950882); + }); + }); + it('should generate correct query string for array params with findRecord', () => { backend.connections.subscribe((c: MockConnection) => { const decodedQueryString = decodeURI(c.request.url).split('?')[1]; diff --git a/src/services/json-api-datastore.service.ts b/src/services/json-api-datastore.service.ts index 6cb98855..b5e04a27 100644 --- a/src/services/json-api-datastore.service.ts +++ b/src/services/json-api-datastore.service.ts @@ -69,6 +69,21 @@ export class JsonApiDatastore { .catch((res: any) => this.handleError(res)); } + findOne( + modelType: ModelType, + id: string, + params?: any, + headers?: Headers, + customUrl?: string + ): Observable> { + const options: RequestOptions = this.getOptions(headers); + const url: string = this.buildUrl(modelType, params, id, customUrl); + + return this.http.get(url, options) + .map((res) => this.extractRecordData(res, modelType, true)) + .catch((res: any) => this.handleError(res)); + } + findRecord( modelType: ModelType, id: string, @@ -135,7 +150,11 @@ export class JsonApiDatastore { } return httpCall - .map((res) => [200, 201].indexOf(res.status) !== -1 ? this.extractRecordData(res, modelType, model) : model) + .map( + (res) => [200, 201].indexOf(res.status) !== -1 + ? this.extractRecordData(res, modelType, false, model) + : model + ) .catch((res) => { if (res == null) { return Observable.of(model); @@ -281,7 +300,12 @@ export class JsonApiDatastore { return new modelType(this, data); } - protected extractRecordData(res: Response, modelType: ModelType, model?: T): T { + protected extractRecordData( + res: Response, + modelType: ModelType, + withMeta = false, + model?: T + ): T | JsonApiQueryData { const body: any = res.json(); if (!body) { @@ -307,6 +331,10 @@ export class JsonApiDatastore { this.addToStore(deserializedModel); } + if (withMeta && withMeta === true) { + return new JsonApiQueryData(deserializedModel, this.parseMeta(body, modelType)); + } + return deserializedModel; } From 0aca287398cb0fd9684a4725c22f9ad1b0036e10 Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sat, 3 Mar 2018 15:00:23 +0100 Subject: [PATCH 5/6] Add information about findOne method to README Signed-off-by: Clemens John --- README.MD | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 06900cf7..878a5760 100644 --- a/README.MD +++ b/README.MD @@ -203,8 +203,14 @@ let posts = this.datastore.peekAll(Post); #### Retrieving a Single Record +Use `findOne()` to retrieve a record by its type and ID including metadata: +```typescript +this.datastore.findOne(Post, '1').subscribe( + (post: JsonApiQueryData) => console.log(post.getModel()) +); +``` -Use `findRecord()` to retrieve a record by its type and ID: +If you dont need Metadata you can use `findRecord()` to retrieve a record by its type and ID: ```typescript this.datastore.findRecord(Post, '1').subscribe( From e9719067670986e803972726d75de91f1015e777 Mon Sep 17 00:00:00 2001 From: Clemens John Date: Sat, 3 Mar 2018 15:53:56 +0100 Subject: [PATCH 6/6] Move code for fetching record into private function Signed-off-by: Clemens John --- src/services/json-api-datastore.service.ts | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/services/json-api-datastore.service.ts b/src/services/json-api-datastore.service.ts index b5e04a27..89357f62 100644 --- a/src/services/json-api-datastore.service.ts +++ b/src/services/json-api-datastore.service.ts @@ -69,19 +69,29 @@ export class JsonApiDatastore { .catch((res: any) => this.handleError(res)); } - findOne( + private fetchRecord( modelType: ModelType, id: string, params?: any, headers?: Headers, - customUrl?: string - ): Observable> { + customUrl?: string, + ): Observable { const options: RequestOptions = this.getOptions(headers); const url: string = this.buildUrl(modelType, params, id, customUrl); - return this.http.get(url, options) - .map((res) => this.extractRecordData(res, modelType, true)) - .catch((res: any) => this.handleError(res)); + return this.http.get(url, options); + } + + findOne( + modelType: ModelType, + id: string, + params?: any, + headers?: Headers, + customUrl?: string + ): Observable> { + return this.fetchRecord(modelType, id, params, headers, customUrl) + .map((res) => this.extractRecordData(res, modelType, true)) + .catch((res: any) => this.handleError(res)); } findRecord( @@ -91,10 +101,7 @@ export class JsonApiDatastore { headers?: Headers, customUrl?: string ): Observable { - const options: RequestOptions = this.getOptions(headers); - const url: string = this.buildUrl(modelType, params, id, customUrl); - - return this.http.get(url, options) + return this.fetchRecord(modelType, id, params, headers, customUrl) .map((res) => this.extractRecordData(res, modelType)) .catch((res: any) => this.handleError(res)); }