diff options
| author | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
|---|---|---|
| committer | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
| commit | bce557cc2dc767628bed6aac87301a1be7c5431b (patch) | |
| tree | b51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet/environment/metrics/parse-and-build-model.js | |
init commit
Diffstat (limited to 'node_modules/@jet/environment/metrics/parse-and-build-model.js')
| -rw-r--r-- | node_modules/@jet/environment/metrics/parse-and-build-model.js | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/node_modules/@jet/environment/metrics/parse-and-build-model.js b/node_modules/@jet/environment/metrics/parse-and-build-model.js new file mode 100644 index 0000000..6f81a59 --- /dev/null +++ b/node_modules/@jet/environment/metrics/parse-and-build-model.js @@ -0,0 +1,116 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseAndBuildModel = exports.requestAndBuildModel = void 0; +const dependencies_1 = require("../dependencies"); +const optional_1 = require("../types/optional"); +const fetch_timing_metrics_builder_1 = require("./fetch-timing-metrics-builder"); +/** + * Returns an object graph guaranteed to have a `FetchTimingMetricsBuilder` object. + * + * If a `FetchTimingMetricsBuilder` already exists, the same object graph is returned. + * + * If it doesn't exist, a new object graph is returned, which has a new `FetchTimingMetricsBuilder` added to it. + */ +function ensureFetchTimingMetricsBuilderExists(objectGraph, errorIfNotFound) { + const optionalBuilder = objectGraph.optional(fetch_timing_metrics_builder_1.fetchTimingMetricsBuilderType); + if ((0, optional_1.isSome)(optionalBuilder)) { + return objectGraph; + } + else { + if (errorIfNotFound) { + throw new Error("Could not find FetchTimingMetricsBuilder in the object graph"); + } + return objectGraph.adding(fetch_timing_metrics_builder_1.fetchTimingMetricsBuilderType, new fetch_timing_metrics_builder_1.FetchTimingMetricsBuilder()); + } +} +/** + * Orchestrates the flow to make a network request and then build the view model, + * capturing timing points around the model building step, and then + * adding performance metrics data to the final result. + * + * **Important** + * + * When using this method, it is the responsibility of the `requester` to instrument the network times and parsing times + * using a `FetchTimingMetricsBuilder` which is in the object graph. + * + * A simplified implementation of a requester function might look like this: +``` + import * as types from "@jet/environment/types/globals/types" + import { fetchTimingMetricsBuilderType } from "@jet/environment/metrics"; + + export async function requestFromAPI(request: FetchRequest, objectGraph: ObjectGraph): Promise<MyParsedModel> { + const net = inject(types.net, objectGraph); + const fetchResponse = await net.fetch(request); + const fetchTimingMetricsBuilder = inject(fetchTimingMetricsBuilderType, objectGraph); + return fetchTimingMetricsBuilder.measureParsing(fetchResponse, (response) => { + const parsedBody = JSON.parse(response.body); + return new MyParsedModel(parsedBody); + }); + } +``` + * This approach supports a common pattern in our adopters in which the code that coordinates the fetch of the network request + * is tightly coupled to the code which parses the response. + * + * For an alternative approach which includes orchestrating the parsing step, use `parseAndBuildModel()`. + * + * @param request - The request object to pass to the `requester` function. + * @param objectGraph - Object graph that can be used to pass data to the `requester` and `modelBuilder` steps. + * The object graph must contain a `FetchTimingMetricsBuilder` that the `requester` will use to collect network times and parsing times. + * @param requester - A function which can make a network request, and return a `ResponseType` which can be used by the `modelBuilder`. + * @param modelBuilder - A step that takes the output of the `requester` step, and builds the view model. + * This parameter supports both synchronous and asynchronous functions. + * @returns The view model. + */ +async function requestAndBuildModel(request, objectGraph, requester, modelBuilder) { + const modifiedObjectGraph = ensureFetchTimingMetricsBuilderExists(objectGraph, true); + const response = await requester(request, modifiedObjectGraph); + return await constructAndDecorateModel(response, modifiedObjectGraph, modelBuilder); +} +exports.requestAndBuildModel = requestAndBuildModel; +/** + * Orchestrates the flow to parse a `FetchResponse` and then build the view model, + * adding performance metrics data to the final result. + * + * Timing points are captured around the parsing and model building steps, + * and this is added to the metrics which were returned from the `FetchResponse`. + * + * When using this method, it is the responsibility of the caller + * to perform the network fetch in order to have a `FetchResponse` object. + * The parsing logic which transforms the `FetchResponse` object into an intermediate model object + * will need to be decoupled so that it can be implemented in the `parser` function. + * + * @param response - The response from a `Network.fetch()` call. + * @param objectGraph - Object graph that can be used to pass data to the `parser` and `renderer` steps. + * @param parser - A step that parses a `FetchResponse` to an intermediate model object. + * @param modelBuilder - A step that takes the output of the `parser` step, and builds the view model. + * This parameter supports both synchronous and asynchronous functions. + * @returns The view model. + */ +async function parseAndBuildModel(response, objectGraph, parser, modelBuilder) { + const modifiedObjectGraph = ensureFetchTimingMetricsBuilderExists(objectGraph, false); + const fetchTimingMetricsBuilder = (0, dependencies_1.inject)(fetch_timing_metrics_builder_1.fetchTimingMetricsBuilderType, modifiedObjectGraph); + // Add metrics from FetchResponse, and run the parser, capturing timing points. + const parsedObject = fetchTimingMetricsBuilder.measureParsing(response, () => { + return parser(response, modifiedObjectGraph); + }); + if ((0, optional_1.isNothing)(parsedObject)) { + throw new Error("parser function returned null or undefined"); + } + return await constructAndDecorateModel(parsedObject, modifiedObjectGraph, modelBuilder); +} +exports.parseAndBuildModel = parseAndBuildModel; +async function constructAndDecorateModel(parsedObject, objectGraph, modelBuilder) { + const fetchTimingMetricsBuilder = (0, dependencies_1.inject)(fetch_timing_metrics_builder_1.fetchTimingMetricsBuilderType, objectGraph); + // Run the model builder, capturing timing points. + const model = await fetchTimingMetricsBuilder.measureModelConstructionAsync(async () => { + const maybePromise = modelBuilder(parsedObject, objectGraph); // The actual model, or a Promise of the model. + return await Promise.resolve(maybePromise); // If it was promise, it will await until the promise is resolved. + }); + if ((0, optional_1.isNothing)(model)) { + throw new Error("model builder function returned null or undefined"); + } + // Decorate the final output with the metrics data. + fetchTimingMetricsBuilder.decorate(model); + return model; +} +//# sourceMappingURL=parse-and-build-model.js.map
\ No newline at end of file |
