init commit

This commit is contained in:
rxliuli
2025-11-04 05:03:50 +08:00
commit bce557cc2d
1396 changed files with 172991 additions and 0 deletions

456
node_modules/@jet/environment/metrics/builder.js generated vendored Normal file
View File

@@ -0,0 +1,456 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMetricsMediaClickData = exports.createMetricsMediaData = exports.createMetricsImpressionsData = exports.createMetricsSearchData = exports.createMetricsPageData = exports.createMetricsBackClickData = exports.createMetricsClickData = exports.MediaClickEventBuilder = exports.MediaEventBuilder = exports.ImpressionsEventBuilder = exports.SearchEventBuilder = exports.PageEventBuilder = exports.BackClickEventBuilder = exports.ClickEventBuilder = exports.EventBuilder = void 0;
const optional_1 = require("../types/optional");
// region Builders
/**
* Base event builder.
*/
class EventBuilder {
/**
* Create base event builder with metrics configuration.
*
* @param configuration - Metrics configuration used to build metrics events.
*/
constructor(configuration) {
this.configuration = configuration;
this.eventFields = {};
}
/**
* Updates event builder with given event fields.
* @param eventFields - The events fields to update in builder.
* @returns Event builder with updated event fields.
*/
withEventFields(eventFields) {
this.eventFields = eventFields;
return this;
}
/**
* Updates event builder with given configuration.
* @param configuration - The configuration to update in builder.
* @returns Event builder with updated configuration.
*/
withConfiguration(configuration) {
this.configuration = configuration;
return this;
}
/**
* Updates event builder with given default topic.
* @param topic - The default topic to update in builder.
* @returns Event builder with updated default topic.
*/
withDefaultTopic(topic) {
this.configuration = {
...this.configuration,
defaultTopic: topic,
};
return this;
}
/**
* Updates event builder with given include fields requests.
* @param includeRequests - The include fields requests to update in builder.
* @returns Event builder with updated include fields requests.
*/
withDefaultIncludeRequests(includeRequests) {
this.configuration = {
...this.configuration,
defaultIncludeRequests: includeRequests,
};
return this;
}
/**
* Updates event builder with given exclude fields requests.
* @param excludeRequests - The exclude fields requests to update in builder.
* @returns Event builder with updated exclude fields requests.
*/
withDefaultExcludeRequests(excludeRequests) {
this.configuration = {
...this.configuration,
defaultExcludeRequests: excludeRequests,
};
return this;
}
/**
* Updates event builder with given flush behavior.
* @param shouldFlush - The flush behavior to update in builder.
* @returns Event builder with updated flush behavior.
*/
withShouldFlush(shouldFlush) {
this.configuration = {
...this.configuration,
shouldFlush: shouldFlush,
};
return this;
}
}
exports.EventBuilder = EventBuilder;
/**
* Builder for click events.
*/
class ClickEventBuilder extends EventBuilder {
/**
* Create click metrics event builder with all required properties.
*
* @param options - Object containing options required to create the builder.
*
* Options:
* - targetId - Target ID used for building events.
* - targetType - Target type used for building events.
* - configuration - Metrics configuration used to build metrics events.
*/
constructor(options) {
super(options.configuration);
this.targetId = options.targetId;
this.targetType = options.targetType;
}
/**
* Updates event builder with given target ID.
* @param targetId - The target ID to update in builder.
* @returns Event builder with updated target ID.
*/
withTargetId(targetId) {
this.targetId = targetId;
return this;
}
/**
* Updates event builder with given target type.
* @param targetType - The target type to update in builder.
* @returns Event builder with updated target type.
*/
withTargetType(targetType) {
this.targetType = targetType;
return this;
}
build() {
return createMetricsClickData(this.targetId, this.targetType, this.eventFields, this.configuration);
}
}
exports.ClickEventBuilder = ClickEventBuilder;
/**
* Builder for back click events.
*/
class BackClickEventBuilder extends EventBuilder {
build() {
return createMetricsBackClickData(this.eventFields, this.configuration);
}
}
exports.BackClickEventBuilder = BackClickEventBuilder;
/**
* Builder for page events.
*/
class PageEventBuilder extends EventBuilder {
/**
* Create page metrics event builder with all required properties.
*
* @param configuration - Metrics configuration used to build metrics events.
*/
constructor(configuration) {
super(configuration);
this.timingMetrics = {};
}
/**
* Updates event builder with given fetch timing metrics.
* @param timingMetrics - The fetch timing metrics to update in builder.
* @returns Event builder with updated fetch timing metrics.
*/
withTimingMetrics(timingMetrics) {
this.timingMetrics = timingMetrics;
return this;
}
build() {
return createMetricsPageData(this.eventFields, this.timingMetrics, this.configuration);
}
}
exports.PageEventBuilder = PageEventBuilder;
/**
* Builder for search metrics events.
*/
class SearchEventBuilder extends EventBuilder {
/**
* Create search metrics event builder with all required properties.
*
* @param options - Object containing options required to create the builder.
*
* Options:
* - term - Search term used to build metrics events.
* - targetType - Target type used to build metrics events.
* - actionType - Action type used to build metrics events.
* - configuration - Metrics configuration used to build metrics events.
*/
constructor(options) {
super(options.configuration);
this.term = options.term;
this.targetType = options.targetType;
this.actionType = options.actionType;
this.actionUrl = null;
}
/**
* Updates event builder with given search term.
* @param term - The search term to update in builder.
* @returns Event builder with updated search term.
*/
withTerm(term) {
this.term = term;
return this;
}
/**
* Updates event builder with given target type.
* @param targetType - The target type to update in builder.
* @returns Event builder with updated target type.
*/
withTargetType(targetType) {
this.targetType = targetType;
return this;
}
/**
* Updates event builder with given action type.
* @param actionType - The action type to update in builder.
* @returns Event builder with updated action type.
*/
withActionType(actionType) {
this.actionType = actionType;
return this;
}
/**
* Updates event builder with given action URL.
* @param actionUrl - The action URL to update in builder.
* @returns Event builder with updated action URL.
*/
withActionUrl(actionUrl) {
this.actionUrl = actionUrl;
return this;
}
build() {
return createMetricsSearchData(this.term, this.targetType, this.actionType, this.actionUrl, this.eventFields, this.configuration);
}
}
exports.SearchEventBuilder = SearchEventBuilder;
/**
* Builder for impressions events.
*/
class ImpressionsEventBuilder extends EventBuilder {
constructor() {
super(...arguments);
/**
* Impressions event version.
*/
this.impressionsEventVersion = 4;
}
/**
* Updates event builder with given impressions event version.
* @param version - The impressions event version to update in builder.
* @returns Event builder with updated impressions event version.
*/
withImpressionsEventVersion(version) {
this.impressionsEventVersion = version;
return this;
}
build() {
return createMetricsImpressionsData(this.eventFields, this.configuration, this.impressionsEventVersion);
}
}
exports.ImpressionsEventBuilder = ImpressionsEventBuilder;
/**
* Builder for media events.
*/
class MediaEventBuilder extends EventBuilder {
build() {
return createMetricsMediaData(this.eventFields, this.configuration);
}
}
exports.MediaEventBuilder = MediaEventBuilder;
/**
* Builder for media click events.
*/
class MediaClickEventBuilder extends EventBuilder {
/**
* Create media click event builder with all required properties.
*
* @param options - Object containing options required to create the builder.
*
* Options:
* - targetId - Target ID used for building events.
* - targetType - Target type used to build metrics events.
* - configuration - Metrics configuration used to build metrics events.
*/
constructor(options) {
super(options.configuration);
this.targetId = options.targetId;
this.targetType = options.targetType;
}
/**
* Updates event builder with given target ID.
* @param targetId - The target ID to update in builder.
* @returns Event builder with updated target ID.
*/
withTargetId(targetId) {
this.targetId = targetId;
return this;
}
/**
* Updates event builder with given target type.
* @param targetType - The target type to update in builder.
* @returns Event builder with updated target type.
*/
withTargetType(targetType) {
this.targetType = targetType;
return this;
}
build() {
return createMetricsMediaClickData(this.targetId, this.targetType, this.eventFields, this.configuration);
}
}
exports.MediaClickEventBuilder = MediaClickEventBuilder;
// region Metrics Data
/**
* Create metrics data for the click event.
*
* @param targetId - The ID of the click event target.
* @param targetType - The type of the click target.
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsClickData(targetId, targetType, eventFields, configuration) {
const eventType = "click" /* MetricsEventType.click */;
const fields = {
...eventFields,
eventType: eventType,
targetType: targetType,
targetId: targetId,
};
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsClickData = createMetricsClickData;
/**
* Create metrics data for the Back button click event.
*
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsBackClickData(eventFields, configuration) {
const fields = {
...eventFields,
actionType: "back",
};
return createMetricsClickData("back", "button" /* MetricsClickTargetType.button */, fields, configuration);
}
exports.createMetricsBackClickData = createMetricsBackClickData;
/**
* Create metrics data for the page event.
* @param eventFields - Event fields to create metrics data from.
* @param timingMetrics - The timing metrics for page data fetching.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsPageData(eventFields, timingMetrics, configuration) {
const eventType = "page" /* MetricsEventType.page */;
const fields = {
...eventFields,
eventType: eventType,
...timingMetrics,
};
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsPageData = createMetricsPageData;
/**
* Create metrics data for search event.
*
* @param term - The search term.
* @param target - The type of the acton target.
* @param actionType - The type of the action.
* @param actionUrl - An optional action URL.
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsSearchData(term, targetType, actionType, actionUrl, eventFields, configuration) {
const eventType = "search" /* MetricsEventType.search */;
const fields = {
...eventFields,
eventType: eventType,
term: term,
targetType: targetType,
actionType: actionType,
};
if ((0, optional_1.isSome)(actionUrl)) {
// actionUrl is defined for `hints` but not for searches fired from elsewhere.
fields["actionUrl"] = actionUrl;
}
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsSearchData = createMetricsSearchData;
/**
* Create metrics data for impressions event.
*
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
* @param impressionsEventVersion - The version of the impressions event.
*/
function createMetricsImpressionsData(eventFields, configuration, impressionsEventVersion = 4) {
const eventType = "impressions" /* MetricsEventType.impressions */;
const fields = {
...eventFields,
eventType: eventType,
impressionQueue: "data-metrics",
eventVersion: impressionsEventVersion,
};
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsImpressionsData = createMetricsImpressionsData;
/**
* Create metrics data for media event.
*
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsMediaData(eventFields, configuration) {
const eventType = "media" /* MetricsEventType.media */;
const fields = {
...eventFields,
eventType: eventType,
};
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsMediaData = createMetricsMediaData;
/**
* Create metrics data for media event.
*
* @param targetId - The ID of the click target.
* @param targetType - The type of the click target.
* @param eventFields - Event fields to create metrics data from.
* @param configuration - Metrics configuration used to create metrics data.
*/
function createMetricsMediaClickData(targetId, targetType, eventFields, configuration) {
const eventType = "click" /* MetricsEventType.click */;
const fields = {
...eventFields,
eventType: eventType,
targetType: targetType,
targetId: targetId,
};
return createMetricsData(fields, configuration, eventType);
}
exports.createMetricsMediaClickData = createMetricsMediaClickData;
// endregion
// region Helpers
function createMetricsData(fields, configuration, eventType) {
return {
fields: fields,
includingFields: configuration.defaultIncludeRequests[eventType],
excludingFields: configuration.defaultExcludeRequests[eventType],
topic: topicFromEventFields(fields, configuration.defaultTopic),
shouldFlush: (0, optional_1.isSome)(configuration.shouldFlush) ? configuration.shouldFlush(fields) : false,
};
}
/**
* Returns event topic for the given event fields.
* @param eventFields - Event fields.
* @param defaultTopic - An optional default topic to use if event fields doesn't have one.
*/
function topicFromEventFields(eventFields, defaultTopic) {
const topic = eventFields["topic"];
if ((0, optional_1.isSome)(topic)) {
return topic;
}
return defaultTopic;
}
// endregion
//# sourceMappingURL=builder.js.map

46
node_modules/@jet/environment/metrics/cookies.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cookieValueForKey = exports.cookiesOf = void 0;
const optional_1 = require("../types/optional");
/**
* Iterate the cookies contained in a string.
*
* @param cookie - A string containing zero or more cookies.
*/
function* cookiesOf(cookie) {
if ((0, optional_1.isNothing)(cookie)) {
return;
}
const rawEntries = cookie.split(";");
for (const rawEntry of rawEntries) {
const keyEndIndex = rawEntry.indexOf("=");
if (keyEndIndex === -1) {
// If there's no splitter, treat the whole raw
// entry as the key and provide an empty value.
const key = decodeURIComponent(rawEntry).trim();
yield { key, value: "" };
}
else {
const key = decodeURIComponent(rawEntry.substring(0, keyEndIndex)).trim();
const value = decodeURIComponent(rawEntry.substring(keyEndIndex + 1)).trim();
yield { key, value };
}
}
}
exports.cookiesOf = cookiesOf;
/**
* Returns value of the cookie with the given key or `null` if there's no such cookie.
*
* @param cookies - Cookies.
* @param key - The key to return cookie value for.
*/
function cookieValueForKey(cookies, key) {
for (const cookie of cookies) {
if (cookie.key === key) {
return cookie.value;
}
}
return null;
}
exports.cookieValueForKey = cookieValueForKey;
//# sourceMappingURL=cookies.js.map

155
node_modules/@jet/environment/metrics/event-linter.js generated vendored Normal file
View File

@@ -0,0 +1,155 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventLinter = void 0;
const object_reader_1 = require("../json/reader/object-reader");
const optional_1 = require("../types/optional");
const numerics = require("./helpers/numerics");
/**
* A type which applies common business rules to metrics fields
* and generates events which are ready for posting to Figaro.
*
* The common business rules are:
* - Add base event fields provided by linter configuration provider object
* - Set clientBuiltType and resourceRevNum fields based on EventLinterEnvironment object values
* - Set xpSendMethod field to "jet-js"
* - Combine pageType and pageId using compound separator provided by linter configuration provider
* and set result to "page" field.
* - Apply event field de-resolution rules provided by linter configuration provider object
* - Set the "position" field for events of "media" type.
*/
class EventLinter {
/**
* Create an event linter.
*
* @param options - The options which specify various behaviors of the new linter.
* This object will be frozen.
*/
constructor(options) {
this.options = Object.freeze(options);
}
// MARK: Public Properties
/**
* Topic to use if an event fields blob does not specify one.
*/
get defaultTopic() {
return this.options.defaultTopic;
}
// MARK: Utilities
/**
* Reduce the accuracy of fields in a blob according to
* a given array of rules provided by linter configuration object.
*
* @param eventFields - The fields of an event to reduce the accuracy of.
* @param rules - An array of de-resolution rules to apply to event fields.
*/
applyDeResolutionRules(eventFields, rules) {
const eventFieldsReader = new object_reader_1.ObjectReader(eventFields);
for (const rule of rules) {
const value = eventFieldsReader.asNumber(rule.fieldName);
if ((0, optional_1.isNothing)(value)) {
continue;
}
let magnitude = rule.magnitude;
if ((0, optional_1.isNothing)(magnitude)) {
magnitude = 1024 * 1024;
}
let significantDigits = rule.significantDigits;
if ((0, optional_1.isNothing)(significantDigits)) {
significantDigits = 2;
}
if (magnitude <= 0.0 || significantDigits < 0.0) {
// This is the failure mode from MetricsKit.
eventFields[rule.fieldName] = Number.NaN;
continue;
}
const scaledValue = value / magnitude;
eventFields[rule.fieldName] = numerics.reduceSignificantDigits(scaledValue, significantDigits);
}
}
// MARK: Rules
/**
* Apply the rules which are universal to all metrics events
* to a given metrics fields linter.
*
* @param eventFields - The fields which will be used to construct a built event.
* @param topic - The topic the built event will be submitted to.
*/
decorateCommonEventFields(eventFields, topic) {
const eventFieldsReader = new object_reader_1.ObjectReader(eventFields);
const configurationProvider = this.options.configuration;
// - Base metrics fields.
const baseFields = configurationProvider.baseFields(topic);
if ((0, optional_1.isSome)(baseFields)) {
Object.assign(eventFields, baseFields);
}
// - Universal basic fields.
eventFields["clientBuildType"] = this.options.environment.buildType;
eventFields["resourceRevNum"] = this.options.environment.jsVersion;
eventFields["xpSendMethod"] = "jet-js";
// - Page.
const pageType = eventFieldsReader.asString("pageType");
const pageId = eventFieldsReader.asString("pageId");
if ((0, optional_1.isSome)(pageType) && (0, optional_1.isSome)(pageId) && (0, optional_1.isNothing)(eventFields["page"])) {
const bagValue = configurationProvider.compoundSeparator(topic);
const separator = (0, optional_1.isSome)(bagValue) ? (0, optional_1.unwrapOptional)(bagValue) : "_";
eventFields["page"] = `${pageType}${separator}${pageId}`;
}
// - Field value resolution reduction.
const rules = configurationProvider.deResolutionRules(topic);
this.applyDeResolutionRules(eventFields, rules);
}
/**
* Apply the rules specific to the `media` event.
*
* @param eventFields - The fields which will be used to construct a built event.
*/
decorateMediaEventEvents(eventFields) {
const eventFieldsReader = new object_reader_1.ObjectReader(eventFields);
const position = eventFieldsReader.asNumber("position");
if ((0, optional_1.isSome)(position)) {
eventFields["position"] = Math.round(position);
}
}
// MARK: Decorating Event Fields
/**
* Lint metrics event fields by applying the common business rules to a given fields blob.
*
* @remarks
*
* Note: A deep copy of event fields is created by linter using `JSON.parse(JSON.stringify(eventFields))`.
* The original event fields are not modified.
*
* @param eventFields - The fields to decorate.
* @param context - The additional event linter context to be passed to all
* event linter rules. This is a free-form object so clients can pass custom
* context information.
* @returns Decorated fields ready for creating a metrics event.
*/
lint(eventFields, context = {}) {
const eventFieldsReader = new object_reader_1.ObjectReader(eventFields);
const eventType = eventFieldsReader.asString("eventType");
if (this.options.isLoggingEnabled) {
console.log(`Building event for event type: ${eventType !== null && eventType !== void 0 ? eventType : "<null>"}`);
}
// Make sure we have a deep copy of an object.
const decoratedEventFields = JSON.parse(JSON.stringify(eventFields));
const value = eventFieldsReader.asString("topic");
const topic = (0, optional_1.isSome)(value) ? (0, optional_1.unwrapOptional)(value) : this.options.defaultTopic;
this.decorateCommonEventFields(decoratedEventFields, topic);
switch (eventType) {
case "media" /* MetricsEventType.media */:
this.decorateMediaEventEvents(decoratedEventFields);
break;
default:
break;
}
for (const rule of this.options.rules) {
rule.apply(decoratedEventFields, context);
}
return {
fields: decoratedEventFields,
};
}
}
exports.EventLinter = EventLinter;
//# sourceMappingURL=event-linter.js.map

View File

@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchTimingMetricsBuilderType = exports.FetchTimingMetricsBuilder = void 0;
const optional_1 = require("../types/optional");
const metatype_1 = require("../util/metatype");
const promise_1 = require("../util/promise");
/** Object to collect `FetchTimingMetrics`, in order to decorate a model object with these metrics. */
class FetchTimingMetricsBuilder {
constructor() {
this.metrics = [];
}
/**
* Collects the timing metrics from the response,
* then execute code for parsing while capturing timing points around it,
* adding those parse times to the first timing metrics.
*/
measureParsing(response, body) {
const responseTimingMetrics = response.metrics.length > 0 ? [...response.metrics] : [];
const parseStartTime = Date.now();
const result = body(response);
const parseEndTime = Date.now();
// MAINTAINERS NOTE:
// Follows app store approach to add additional timing points to the first item.
// This may not be strictly correct, and we should revisit this later.
if (responseTimingMetrics.length > 0) {
responseTimingMetrics[0].parseStartTime = parseStartTime;
responseTimingMetrics[0].parseEndTime = parseEndTime;
}
this.metrics.push(...responseTimingMetrics);
return result;
}
/**
* Execute code for model construction while capturing timing points around it,
* adding those model construction times to the first timing metrics.
*
* Use this method when model construction is a synchronous operation.
* Use `measureModelConstructionAsync()` when model construction is an asynchronous operation.
*/
measureModelConstruction(body) {
const buildModelStartTime = Date.now();
const result = body();
const buildModelEndTime = Date.now();
this.saveModelConstructionTimes(buildModelStartTime, buildModelEndTime);
return result;
}
/**
* Execute and await code for an asynchronous model construction operation while capturing timing points around it,
* adding those model construction times to the first timing metrics.
*
* Use this method when model construction is an asynchronous operation.
* Use `measureModelConstruction()` when model construction is a synchronous operation.
*/
async measureModelConstructionAsync(body) {
const buildModelStartTime = Date.now();
const result = await body();
const buildModelEndTime = Date.now();
this.saveModelConstructionTimes(buildModelStartTime, buildModelEndTime);
return result;
}
saveModelConstructionTimes(startTime, endTime) {
// MAINTAINERS NOTE:
// Follows app store approach to add additional timing points to the first item.
// This may not be strictly correct, and we should revisit this later.
if (this.metrics.length > 0) {
this.metrics[0].modelConstructionStartTime = startTime;
this.metrics[0].modelConstructionEndTime = endTime;
}
else {
this.metrics.push({
modelConstructionStartTime: startTime,
modelConstructionEndTime: endTime,
});
}
}
/** Add the recorded `FetchTimingMetrics` as an additional property on the model. */
decorate(model) {
if ((0, optional_1.isNothing)(model)) {
throw new Error("Cannot decorate null or undefined");
}
if (typeof model !== "object") {
throw new Error("View model to decorate must be an object");
}
if ((0, promise_1.isPromise)(model)) {
// TypeScript compiler may be able to enforce this at compile time.
// A newer version of TypeScript which supports `Awaited` type may help.
throw new Error("Cannot decorate a Promise object");
}
if (this.metrics.length > 0) {
model["$networkPerformance"] = this.metrics;
}
}
}
exports.FetchTimingMetricsBuilder = FetchTimingMetricsBuilder;
/** Metatype for the `FetchTimingMetricsBuilder`, for adding to an object graph. */
exports.fetchTimingMetricsBuilderType = (0, metatype_1.makeMetatype)("jet-engine:fetchTimingMetricsBuilder");
//# sourceMappingURL=fetch-timing-metrics-builder.js.map

21
node_modules/@jet/environment/metrics/helpers/index.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./location"), exports);
__exportStar(require("./models"), exports);
__exportStar(require("./numerics"), exports);
__exportStar(require("./util"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,213 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricsLocationTracker = void 0;
const validation = require("../../json/validation");
const optional_1 = require("../../types/optional");
const metricsUtil = require("./util");
/**
* A type describing metrics location tracker.
*
* The tracker manages stack of metrics location items.
*/
class MetricsLocationTracker {
// endregion
// region Initialization
/**
* Create new metrics location tracker with all required attributes.
* @param rootPosition - Current root position of the tracker.
* @param locations - Array of metrics location to track.
*/
constructor(rootPosition = 0, locations = []) {
this.rootPosition = rootPosition;
this.locationStack = locations.map((location) => new MetricsLocationStackItem(location));
}
// endregion
// region Location Stack Management
/**
* Check whether location stack is empty or not.
*/
get isEmpty() {
return this.locationStack.length === 0;
}
/**
* Push new location to location tracker's stack.
* @param location - Location to push to stack.
*/
pushLocation(location) {
this.locationStack.push(new MetricsLocationStackItem(location));
}
/**
* Pop location from location tracker's stack.
*/
popLocation() {
var _a;
if (this.locationStack.length === 0) {
validation.unexpectedType("ignoredValue", "non-empty location stack", "empty location stack");
return null;
}
return (_a = this.locationStack.pop()) === null || _a === void 0 ? void 0 : _a.location;
}
/**
* Returns tracker's current position.
*/
get currentPosition() {
const stackItem = this.lastStackItem;
if ((0, optional_1.isSome)(stackItem)) {
return stackItem.position;
}
else {
return this.rootPosition;
}
}
/**
* Set current position of tracker.
* This is necessary when large today modules are broken apart into multipart shelves.
* We need to preserve the position of content within server-response, not our logical shelves.
* @param position - Position to set to.
*/
setCurrentPosition(position) {
const stackItem = this.lastStackItem;
if ((0, optional_1.isSome)(stackItem)) {
stackItem.position = position;
}
else {
this.rootPosition = position;
}
}
/**
* Advance tracker's position.
*/
nextPosition() {
const stackItem = this.lastStackItem;
if ((0, optional_1.isSome)(stackItem)) {
stackItem.position += 1;
}
else {
this.rootPosition += 1;
}
}
/**
* Convert location tracker's stack items to array of metric location objects.
*/
get stackItemsToLocations() {
return this.locationStack.map((stackItem) => stackItem.location);
}
/**
* Returns last stack item in location stack or `null` if stack is empty.
*/
get lastStackItem() {
const length = this.locationStack.length;
if (length === 0) {
return null;
}
return this.locationStack[length - 1];
}
// endregion
// region Adding Location
/**
* Create new basic location and add it to existing locations of the location tracker
* and return resulting array of locations.
* @param options - Base metrics options which include location tracker to get current locations from.
* @param title - New location title.
*/
static locationsByAddingBasicLocation(options, title) {
const locations = options.locationTracker.stackItemsToLocations;
locations.push(MetricsLocationTracker.buildBasicLocation(options, title));
return locations;
}
/**
* Create new content location and add it to existing locations of the location tracker
* and return resulting array of locations.
* @param options - Content metrics options which include location tracker to get current locations from.
* @param title - New location title.
*/
static locationsByAddingContentLocation(options, title) {
const locations = options.locationTracker.stackItemsToLocations;
locations.push(MetricsLocationTracker.buildContentLocation(options, title));
return locations;
}
// endregion
// region Metrics Options
/**
* Create new basic location from base metrics options
* and push it to the stack of location tracker included into options.
* @param options - Base metrics options which include location tracker to push new location to.
* @param title - Location title.
*/
static pushBasicLocation(options, title) {
options.locationTracker.pushLocation(MetricsLocationTracker.buildBasicLocation(options, title));
}
/**
* Create new content location from content metrics options
* and push it to the stack of location tracker included into options.
* @param options - Content metrics options which include location tracker to push new location to.
* @param title - Location title.
*/
static pushContentLocation(options, title) {
options.locationTracker.pushLocation(MetricsLocationTracker.buildContentLocation(options, title));
}
/**
* Pop last location from location tracker contained in metrics options.
* @param options - Metrics options containing the location tracker.
*/
static popLocation(options) {
return options.locationTracker.popLocation();
}
// endregion
// region Location Builders
static buildBasicLocation(options, title) {
let name = title;
if ((0, optional_1.isSome)(options.anonymizationOptions)) {
name = options.anonymizationOptions.anonymizationString;
}
const location = {
locationPosition: options.locationTracker.currentPosition,
locationType: metricsUtil.targetTypeForMetricsOptions(options),
name: name,
};
if ((0, optional_1.isSome)(options.recoMetricsData)) {
Object.assign(location, options.recoMetricsData);
}
return location;
}
static buildContentLocation(options, title) {
const base = MetricsLocationTracker.buildBasicLocation(options, title);
// Use the location tracker if there is no id override.
if ((0, optional_1.isNothing)(options.id)) {
base.idType = "sequential" /* MetricsIDType.sequential */;
base.id = options.locationTracker.currentPosition.toString();
}
else {
// If there is a id specified, use that.
base.idType = metricsUtil.idTypeForMetricsOptions(options);
let id = options.id;
if ((0, optional_1.isSome)(options.anonymizationOptions)) {
id = options.anonymizationOptions.anonymizationString;
}
base.id = id;
}
if ((0, optional_1.isSome)(options.fcKind)) {
base.fcKind = options.fcKind;
}
if ((0, optional_1.isSome)(options.displayStyle)) {
base.displayStyle = options.displayStyle;
}
return base;
}
}
exports.MetricsLocationTracker = MetricsLocationTracker;
/**
* A type describing a metrics location item in location tracking stack.
*/
class MetricsLocationStackItem {
/**
* Create new metrics location stack item with all required attributes.
* @param location - The metrics location associated with this item.
* @param position - The position of the item.
*/
constructor(location, position = 0) {
this.location = location;
this.position = position;
}
}
//# sourceMappingURL=location.js.map

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=models.js.map

View File

@@ -0,0 +1,23 @@
"use strict";
/**
* Number related helper functions for metrics.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.reduceSignificantDigits = void 0;
/**
* Reduce significant figures of `value` by `significantDigits`.
* @param value - Value to reduce precision of.
* @param significantDigits - Number of significant digits to reduce precision by.
*
* Examples:
* value = 123.5, significantDigits = 0, result = 120 (no significant digit reduced)
* value = 123.5, significantDigits = 1, result = 120 (1 significant digit reduced)
* value = 123.5, significantDigits = 2, result = 100 (2 significant digit reduced)
*/
function reduceSignificantDigits(value, significantDigits) {
const roundFactor = Math.pow(10.0, significantDigits);
const roundingFunction = value > 0.0 ? Math.floor : Math.ceil;
return roundingFunction(value / roundFactor) * roundFactor;
}
exports.reduceSignificantDigits = reduceSignificantDigits;
//# sourceMappingURL=numerics.js.map

76
node_modules/@jet/environment/metrics/helpers/util.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.searchTermFromRefURL = exports.extractSiriRefAppFromRefURL = exports.idTypeForMetricsOptions = exports.targetTypeForMetricsOptions = void 0;
const optional_1 = require("../../types/optional");
const urls = require("../../util/urls");
/**
* Returns click target type for given base metrics options.
* @param options - Base metrics options to derive click target type for.
*/
function targetTypeForMetricsOptions(options) {
let type = options.targetType;
if ((0, optional_1.isNothing)(type)) {
type = "lockup" /* MetricsClickTargetType.lockup */;
}
return type;
}
exports.targetTypeForMetricsOptions = targetTypeForMetricsOptions;
/**
* Returns metrics ID type for given content metrics options.
* @param options - Content metrics options to derive metrics ID type for.
*/
function idTypeForMetricsOptions(options) {
let type = options.idType;
if ((0, optional_1.isNothing)(type)) {
type = "its_id" /* MetricsIDType.itsID */;
}
return type;
}
exports.idTypeForMetricsOptions = idTypeForMetricsOptions;
/**
* Extract and return Siri reference app from URL string.
* @param refUrlString - URL string.
* @returns An optional Siri reference app string.
*/
function extractSiriRefAppFromRefURL(urlString) {
const refUrl = new urls.URL(urlString);
if ((0, optional_1.isNothing)(refUrl.query)) {
return null;
}
let extractedRefApp = null;
for (const key of Object.keys(refUrl.query)) {
if (key === "referrer") {
if (refUrl.query[key] === "siri") {
extractedRefApp = "com.apple.siri";
}
break;
}
}
return extractedRefApp;
}
exports.extractSiriRefAppFromRefURL = extractSiriRefAppFromRefURL;
/**
* Extract and return search term from reference URL string.
* @param refUrlString - Reference URL string.
* @returns An optional search term string.
*/
function searchTermFromRefURL(refUrlString) {
const refUrl = new urls.URL(refUrlString);
const queryItems = refUrl.query;
if ((0, optional_1.isNothing)(queryItems)) {
return null;
}
const searchTerm = queryItems["term"];
const path = refUrl.pathname;
if ((0, optional_1.isNothing)(searchTerm) || (0, optional_1.isNothing)(path)) {
return null;
}
if (!path.endsWith("/search")) {
return null;
}
// the url object has already url-decoded this query parameter
const plainTerm = searchTerm;
return plainTerm;
}
exports.searchTermFromRefURL = searchTermFromRefURL;
//# sourceMappingURL=util.js.map

23
node_modules/@jet/environment/metrics/index.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./builder"), exports);
__exportStar(require("./cookies"), exports);
__exportStar(require("./event-linter"), exports);
__exportStar(require("./fetch-timing-metrics-builder"), exports);
__exportStar(require("./helpers"), exports);
__exportStar(require("./parse-and-build-model"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -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