1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/**
* Created by ls on 9/7/2018.
*
* This `network.ts` is the NON-MEDIA API arm of network fetch requests.
* It is built on `Network` object and provides standard functionality, such as:
* 1. Parsing the body into specific format.
* 2. Adding timing metrics onto blob.
*
* This should *only* be used for objects that should have timing metrics, i.e. requests to Non-MediaAPI endpoints
* that will ultimately render some whole page. Otherwise, use `objectGraph.network.fetch` directly.
*
* @see `src/media/network.ts` for fetching from Media API endpoints
*/
import { isSome } from "@jet/environment/types/optional";
import * as serverData from "../json-parsing/server-data";
/** @public */
// eslint-disable-next-line @typescript-eslint/no-namespace
export var ResponseMetadata;
(function (ResponseMetadata) {
ResponseMetadata.requestedUrl = "_jet-internal:metricsHelpers_requestedUrl";
/**
* Symbol used to place timing metrics values onto fetch responses
* without interfering with the data returned by the server.
*/
ResponseMetadata.timingValues = "_jet-internal:metricsHelpers_timingValues";
/**
* Key used to access the page information gathered from a response's headers
*/
ResponseMetadata.pageInformation = "_jet-internal:metricsHelpers_pageInformation";
/**
* Key used to access the content max-age gathered from a response's headers.
*/
ResponseMetadata.contentMaxAge = "_jet-internal:responseMetadata_contentMaxAge";
})(ResponseMetadata || (ResponseMetadata = {}));
/**
* Module's private fetch implementation built off `net` global.
*
* @param {FetchRequest} request describes fetch request.
* @param {(value: string) => Type} parser Some function parsing response body `string` into specific type.
* @returns {Promise<Type>} Promise resolving to specific object.
* @throws {Error} Throws error if status code of request is not 200.
*
* @note Similar to `fetchWithToken` in `media` module, but excludes media token specific functionality.
* Top level data fetches to endpoints that don't do redirects, and can benefit from metrics should
* call methods that build off of this instead of calling `objectGraph.network.fetch(...)` directly.
*/
async function fetch(objectGraph, request, parser) {
const response = await objectGraph.network.fetch(request);
if (!response.ok) {
throw Error(`Bad Status code ${response.status} for ${request.url}`);
}
const parseStartTime = Date.now();
const result = parser(response.body);
const parseEndTime = Date.now();
if (result) {
// Build full network timing metrics.
const completeTimingMetrics = networkTimingMetricsWithParseTime(response.metrics, parseStartTime, parseEndTime);
if (serverData.isDefinedNonNull(completeTimingMetrics)) {
result[ResponseMetadata.timingValues] = completeTimingMetrics;
}
}
result[ResponseMetadata.requestedUrl] = request.url.toString();
return result;
}
/**
* Fetch from an endpoint with JSON response body.
*
* @param {FetchRequest} request to fetch from endpoint with JSON response..
* @returns {Promise<Type>} Promise resolving to body of response parsed as `Type`.
* @throws {Error} Throws error if status code of request is not 200.
*/
export async function fetchJSON(objectGraph, request) {
return await fetch(objectGraph, request, (body) => {
if (isSome(body)) {
return JSON.parse(body);
}
else {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {};
}
});
}
/**
* Fetch from an endpoint with XML response body.
*
* @param {FetchRequest} request to fetch from endpoint with XML response.
* @returns {Promise<Type>} Promise resolving to body of response parsed as `Type`.
* @throws {Error} Throws error if status code of request is not 200.
*/
export async function fetchPlist(objectGraph, request) {
return await fetch(objectGraph, request, (body) => {
if (isSome(body)) {
return objectGraph.plist.parse(body);
}
else {
throw new Error(`Could not fetch Plist, response body was not defined for ${request.url}`);
}
});
}
/**
* With network requests now being created and parsed in JS, different timing metrics are measured in both Native and JS.
* This function populates the missing values from `HTTPTimingMetrics`'s native counterpart, `JSNetworkPerformanceMetrics`.
*
* @param {HTTPTimingMetrics[] | null} responseMetrics Array of response metrics provided by native.
* @param {number} parseStartTime Time at which response body string parse began in JS.
* @param {number} parseEndTime Time at which response body string parse ended in JS.
* @returns {HTTPTimingMetrics | null} Fully populated timing metrics, or `null` if native response provided no metrics events to build off of.
*/
function networkTimingMetricsWithParseTime(responseMetrics, parseStartTime, parseEndTime) {
// No metrics events to build from.
if (serverData.isNull(responseMetrics) || responseMetrics.length === 0) {
return null;
}
// Append parse times to first partial timing metrics from native.
const firstPartialTimingMetrics = {
...responseMetrics[0],
parseStartTime: parseStartTime,
parseEndTime: parseEndTime,
};
// Timing metrics with all properties populated.
return firstPartialTimingMetrics;
}
//# sourceMappingURL=network.js.map
|