summaryrefslogtreecommitdiff
path: root/node_modules/@apple-media-services/media-api/src/models/attributes.ts
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@apple-media-services/media-api/src/models/attributes.ts')
-rw-r--r--node_modules/@apple-media-services/media-api/src/models/attributes.ts289
1 files changed, 289 insertions, 0 deletions
diff --git a/node_modules/@apple-media-services/media-api/src/models/attributes.ts b/node_modules/@apple-media-services/media-api/src/models/attributes.ts
new file mode 100644
index 0000000..edb5fca
--- /dev/null
+++ b/node_modules/@apple-media-services/media-api/src/models/attributes.ts
@@ -0,0 +1,289 @@
+import { Opt, isNothing } from "@jet/environment/types/optional";
+import * as serverData from "./server-data";
+import * as media from "./data-structure";
+import { JSONValue, MapLike, JSONData } from "./json-types";
+import * as errors from "./errors";
+
+// region Generic Attribute retrieval
+
+// region Attribute retrieval
+
+/**
+ * Retrieve the specified attribute from the data, coercing it to a JSONData dictionary
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns The dictionary of data
+ */
+export function attributeAsDictionary<Type extends JSONValue>(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ defaultValue?: MapLike<Type>,
+): MapLike<Type> | null {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ return serverData.asDictionary(data.attributes, attributePath, defaultValue);
+}
+
+/**
+ * Retrieve the specified attribute from the data, coercing it to an Interface
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns The dictionary of data as an interface
+ */
+export function attributeAsInterface<Interface>(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ defaultValue?: JSONData,
+): Interface | null {
+ return attributeAsDictionary(data, attributePath, defaultValue) as unknown as Interface;
+}
+
+/**
+ * Retrieve the specified attribute from the data as an array, coercing to an empty array if the object is not an array.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @returns {any[]} The attribute value as an array.
+ */
+export function attributeAsArrayOrEmpty<T extends JSONValue>(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+): T[] {
+ if (serverData.isNull(data)) {
+ return [];
+ }
+ return serverData.asArrayOrEmpty(data.attributes, attributePath);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a string.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The object path for the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {string} The attribute value as a string.
+ */
+export function attributeAsString(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ policy: serverData.ValidationPolicy = "coercible",
+): Opt<string> {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ return serverData.asString(data.attributes, attributePath, policy);
+}
+
+/**
+ * Retrieve the specified meta from the data as a string.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param metaPath The object path for the meta.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {string} The meta value as a string.
+ */
+export function metaAsString(
+ data: media.Data,
+ metaPath?: serverData.ObjectPath,
+ policy: serverData.ValidationPolicy = "coercible",
+): Opt<string> {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ return serverData.asString(data.meta, metaPath, policy);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a date.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The object path for the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {Date} The attribute value as a date.
+ */
+export function attributeAsDate(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ policy: serverData.ValidationPolicy = "coercible",
+): Opt<Date> {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ const dateString = serverData.asString(data.attributes, attributePath, policy);
+ if (isNothing(dateString)) {
+ return null;
+ }
+ return new Date(dateString);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a boolean.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {boolean} The attribute value as a boolean.
+ */
+export function attributeAsBoolean(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ policy: serverData.ValidationPolicy = "coercible",
+): boolean | null {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ return serverData.asBoolean(data.attributes, attributePath, policy);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a boolean, which will be `false` if the attribute does not exist.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @returns {boolean} The attribute value as a boolean, coercing to `false` if the value is not present..
+ */
+export function attributeAsBooleanOrFalse(data: media.Data, attributePath?: serverData.ObjectPath): boolean {
+ if (serverData.isNull(data)) {
+ return false;
+ }
+ return serverData.asBooleanOrFalse(data.attributes, attributePath);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a number.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {boolean} The attribute value as a number.
+ */
+export function attributeAsNumber(
+ data: media.Data,
+ attributePath?: serverData.ObjectPath,
+ policy: serverData.ValidationPolicy = "coercible",
+): Opt<number> {
+ if (serverData.isNull(data)) {
+ return null;
+ }
+ return serverData.asNumber(data.attributes, attributePath, policy);
+}
+
+export function hasAttributes(data: media.Data): boolean {
+ return !serverData.isNull(serverData.asDictionary(data, "attributes"));
+}
+
+/**
+ * The canonical way to detect if an item from Media API is hydrated or not.
+ *
+ * @param data The data from which to retrieve the attributes.
+ */
+export function isNotHydrated(data: media.Data): boolean {
+ return !hasAttributes(data);
+}
+
+// region Custom Attributes
+
+/**
+ * Performs conversion for a custom variant of given attribute, if any are available.
+ * @param attribute Attribute to get custom attribute key for, if any.
+ */
+export function attributeKeyAsCustomAttributeKey(attribute: string): string | undefined {
+ return customAttributeMapping[attribute];
+}
+
+/**
+ * Whether or not given custom attributes key allows fallback to default page with AB testing treatment within a nondefault page.
+ * This is to allow AB testing to affect only icons within custom product pages.
+ */
+export function attributeAllowsNonDefaultTreatmentInNonDefaultPage(customAttribute: string): boolean {
+ return customAttribute === "customArtwork" || customAttribute === "customIconArtwork"; // Only the icon artwork.
+}
+
+/**
+ * Defines mapping of attribute to custom attribute.
+ */
+const customAttributeMapping: { [key: string]: string } = {
+ artwork: "customArtwork",
+ iconArtwork: "customIconArtwork",
+ screenshotsByType: "customScreenshotsByType",
+ promotionalText: "customPromotionalText",
+ videoPreviewsByType: "customVideoPreviewsByType",
+ customScreenshotsByTypeForAd: "customScreenshotsByTypeForAd",
+ customVideoPreviewsByTypeForAd: "customVideoPreviewsByTypeForAd",
+};
+
+export function requiredAttributeAsString(data: media.Data, attributePath: serverData.ObjectPath): string {
+ const value = attributeAsString(data, attributePath);
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+ }
+ return value;
+}
+
+export function requiredAttributeAsDate(data: media.Data, attributePath: serverData.ObjectPath): Date {
+ const value = attributeAsDate(data, attributePath);
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+ }
+ return value;
+}
+
+export function requiredAttributeAsDictionary<Type extends JSONValue>(
+ data: media.Data,
+ attributePath: serverData.ObjectPath,
+): MapLike<Type> {
+ const value: MapLike<Type> | null = attributeAsDictionary(data, attributePath);
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+ }
+ return value;
+}
+
+export function requiredMeta(data: media.Data): MapLike<JSONValue> {
+ const value = serverData.asDictionary(data, "meta");
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, "meta");
+ }
+ return value;
+}
+
+export function requiredMetaAttributeAsString(data: media.Data, attributePath: serverData.ObjectPath): string {
+ const meta = requiredMeta(data);
+ const value = serverData.asString(meta, attributePath);
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, concatObjectPaths("meta", attributePath));
+ }
+ return value;
+}
+
+export function requiredMetaAttributeAsNumber(data: media.Data, attributePath: serverData.ObjectPath): number {
+ const meta = requiredMeta(data);
+ const value = serverData.asNumber(meta, attributePath);
+ if (isNothing(value)) {
+ throw new errors.MissingFieldError(data, concatObjectPaths("meta", attributePath));
+ }
+ return value;
+}
+
+export function concatObjectPaths(prefix: serverData.ObjectPath, suffix: serverData.ObjectPath): serverData.ObjectPath {
+ let finalPath: string[];
+ if (Array.isArray(prefix)) {
+ finalPath = prefix;
+ } else {
+ finalPath = [prefix];
+ }
+
+ if (Array.isArray(suffix)) {
+ finalPath.push(...suffix);
+ } else {
+ finalPath.push(suffix);
+ }
+ return finalPath;
+}
+
+// endregion