Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit 19445ef

Browse files
rewrite of the odata pipeline to move responsibility 100% to parsers for handling response, update to rreturn an object with etag for item update
1 parent 5124a1e commit 19445ef

4 files changed

Lines changed: 55 additions & 49 deletions

File tree

src/sharepoint/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export {
2525
export {
2626
ItemAddResult,
2727
ItemUpdateResult,
28+
ItemUpdateResultData,
2829
PagedItemCollection
2930
} from "./items";
3031

src/sharepoint/items.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export class Item extends QueryableSecurable {
188188
"IF-Match": eTag,
189189
"X-HTTP-Method": "MERGE",
190190
},
191-
}).then((data) => {
191+
}, new ItemUpdatedParser()).then((data) => {
192192
removeDependency();
193193
resolve({
194194
data: data,
@@ -257,7 +257,11 @@ export interface ItemAddResult {
257257

258258
export interface ItemUpdateResult {
259259
item: Item;
260-
data: any;
260+
data: ItemUpdateResultData;
261+
}
262+
263+
export interface ItemUpdateResultData {
264+
"odata.etag": string;
261265
}
262266

263267
/**
@@ -291,9 +295,28 @@ export class PagedItemCollection<T> {
291295
class PagedItemCollectionParser extends ODataParserBase<PagedItemCollection<any>> {
292296
public parse(r: Response): Promise<PagedItemCollection<any>> {
293297

294-
return r.json().then(json => {
295-
let nextUrl = json.hasOwnProperty("d") && json.d.hasOwnProperty("__next") ? json.d.__next : json["odata.nextLink"];
296-
return new PagedItemCollection(nextUrl, this.parseODataJSON(json));
298+
return new Promise<PagedItemCollection<any>>((resolve, reject) => {
299+
300+
if (this.handleError(r, reject)) {
301+
r.json().then(json => {
302+
let nextUrl = json.hasOwnProperty("d") && json.d.hasOwnProperty("__next") ? json.d.__next : json["odata.nextLink"];
303+
resolve(new PagedItemCollection(nextUrl, this.parseODataJSON(json)));
304+
});
305+
}
306+
});
307+
}
308+
}
309+
310+
class ItemUpdatedParser extends ODataParserBase<ItemUpdateResultData> {
311+
public parse(r: Response): Promise<ItemUpdateResultData> {
312+
313+
return new Promise<ItemUpdateResultData>((resolve, reject) => {
314+
315+
if (this.handleError(r, reject)) {
316+
resolve({
317+
"odata.etag": r.headers.get("etag"),
318+
});
319+
}
297320
});
298321
}
299322
}

src/sharepoint/odata.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { HttpClient } from "../net/httpclient";
55
import { RuntimeConfig } from "../configuration/pnplibconfig";
66
import { TypedHash } from "../collections/collections";
77
import { ODataIdException, BatchParseException } from "../utils/exceptions";
8+
import { ProcessHttpClientResponseException } from "../utils/exceptions";
89

910
export function extractOdataId(candidate: any): string {
1011

@@ -24,7 +25,26 @@ export interface ODataParser<U> {
2425
export abstract class ODataParserBase<U> implements ODataParser<U> {
2526

2627
public parse(r: Response): Promise<U> {
27-
return r.json().then(json => this.parseODataJSON(json));
28+
29+
return new Promise<U>((resolve, reject) => {
30+
31+
if (this.handleError(r, reject)) {
32+
if ((r.headers.has("Content-Length") && parseFloat(r.headers.get("Content-Length")) === 0) || r.status === 204) {
33+
resolve(<U>{});
34+
} else {
35+
r.json().then(json => resolve(this.parseODataJSON<U>(json)));
36+
}
37+
}
38+
});
39+
}
40+
41+
protected handleError(r: Response, reject: (reason?: any) => void): boolean {
42+
if (!r.ok) {
43+
r.json().then(json => {
44+
reject(new ProcessHttpClientResponseException(r.status, r.statusText, json));
45+
});
46+
}
47+
return r.ok;
2848
}
2949

3050
protected parseODataJSON<U>(json: any): U {

src/sharepoint/queryable.ts

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FetchOptions, HttpClient } from "../net/httpclient";
44
import { ODataParser, ODataDefaultParser, ODataBatch } from "./odata";
55
import { ICachingOptions, CachingParserWrapper, CachingOptions } from "./caching";
66
import { RuntimeConfig } from "../configuration/pnplibconfig";
7-
import { ProcessHttpClientResponseException, AlreadyInBatchException } from "../utils/exceptions";
7+
import { AlreadyInBatchException } from "../utils/exceptions";
88

99
export interface QueryableConstructor<T> {
1010
new (baseUrl: string | Queryable, path?: string): T;
@@ -271,9 +271,7 @@ export class Queryable {
271271

272272
// we are not part of a batch, so proceed as normal
273273
let client = new HttpClient();
274-
return client.get(this.toUrlAndQuery(), getOptions).then((response) => {
275-
return this.processHttpClientResponse(response, parser);
276-
});
274+
return client.get(this.toUrlAndQuery(), getOptions).then((response) => parser.parse(response));
277275

278276
} else {
279277

@@ -287,9 +285,7 @@ export class Queryable {
287285

288286
// we are not part of a batch, so proceed as normal
289287
let client = new HttpClient();
290-
return client.post(this.toUrlAndQuery(), postOptions).then((response) => {
291-
return this.processHttpClientResponse(response, parser);
292-
});
288+
return client.post(this.toUrlAndQuery(), postOptions).then((response) => parser.parse(response));
293289

294290
} else {
295291
return this._batch.add(this.toUrlAndQuery(), "POST", postOptions, parser);
@@ -302,9 +298,7 @@ export class Queryable {
302298

303299
// we are not part of a batch, so proceed as normal
304300
let client = new HttpClient();
305-
return client.patch(this.toUrlAndQuery(), patchOptions).then((response) => {
306-
return this.processHttpClientResponse(response, parser);
307-
});
301+
return client.patch(this.toUrlAndQuery(), patchOptions).then((response) => parser.parse(response));
308302

309303
} else {
310304
return this._batch.add(this.toUrlAndQuery(), "PATCH", patchOptions, parser);
@@ -317,44 +311,12 @@ export class Queryable {
317311

318312
// we are not part of a batch, so proceed as normal
319313
let client = new HttpClient();
320-
return client.delete(this.toUrlAndQuery(), deleteOptions).then((response) => {
321-
return this.processHttpClientResponse(response, parser);
322-
});
314+
return client.delete(this.toUrlAndQuery(), deleteOptions).then((response) => parser.parse(response));
323315

324316
} else {
325317
return this._batch.add(this.toUrlAndQuery(), "DELETE", deleteOptions, parser);
326318
}
327319
}
328-
329-
private processHttpClientResponse<T>(response: Response, parser: ODataParser<T>): Promise<T> {
330-
331-
return new Promise<T>((resolve, reject) => {
332-
333-
// 200 = OK (get, delete)
334-
// 201 = Created (create)
335-
// 204 = No Content (update)
336-
if (response.ok) {
337-
338-
if ((response.headers.has("Content-Length") && parseFloat(response.headers.get("Content-Length")) === 0)
339-
|| response.status === 204) {
340-
341-
// in these cases the server has returned no content, so we create an empty object
342-
// this was done because the fetch browser methods throw exceptions with no content
343-
return resolve(<T>{});
344-
}
345-
346-
// pipe our parsed content
347-
return resolve(parser.parse(response));
348-
349-
} else {
350-
351-
// and reject
352-
response.json().then(json => {
353-
return reject(new ProcessHttpClientResponseException(response.status, response.statusText, json));
354-
});
355-
}
356-
});
357-
}
358320
}
359321

360322
/**

0 commit comments

Comments
 (0)