summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js464
1 files changed, 464 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js b/node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js
new file mode 100644
index 0000000..2ff6394
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/foundation/json-parsing/server-data.js
@@ -0,0 +1,464 @@
+//
+// server-data.ts
+// AppStoreKit
+//
+// Created by Kevin MacWhinnie on 8/17/16.
+// Copyright (c) 2016 Apple Inc. All rights reserved.
+//
+import * as validation from "@jet/environment/json/validation";
+import { isNothing } from "@jet/environment/types/optional";
+/**
+ * Returns the string representation of a given object path.
+ * @param path The object path to coerce to a string.
+ * @returns A string representation of `path`.
+ */
+export function objectPathToString(path) {
+ if (isNull(path)) {
+ return null;
+ }
+ else if (Array.isArray(path)) {
+ return path.join(".");
+ }
+ else {
+ return path;
+ }
+}
+const PARSED_PATH_CACHE = {};
+/**
+ * Traverse a nested JSON object structure, short-circuiting
+ * when finding `undefined` or `null` values. Usage:
+ *
+ * const object = {x: {y: {z: 42}}};
+ * const meaningOfLife = serverData.traverse(object, 'x.y.z');
+ *
+ * @param object The JSON object to traverse.
+ * @param path The path to search. If falsy, `object` will be returned without being traversed.
+ * @param defaultValue The object to return if the path search fails.
+ * @return The value at `path` if found; default value otherwise.
+ */
+export function traverse(object, path, defaultValue) {
+ if (object === undefined || object === null) {
+ return defaultValue;
+ }
+ if (!path) {
+ return object;
+ }
+ let components;
+ if (typeof path === "string") {
+ components = PARSED_PATH_CACHE[path];
+ if (!components) {
+ // Fast Path: If the path contains only a single component, we can skip
+ // all of the work below here and speed up storefronts that
+ // don't have JIT compilation enabled.
+ if (!path.includes(".")) {
+ const value = object[path];
+ if (value !== undefined && value !== null) {
+ return value;
+ }
+ else {
+ return defaultValue;
+ }
+ }
+ components = path.split(".");
+ PARSED_PATH_CACHE[path] = components;
+ }
+ }
+ else {
+ components = path;
+ }
+ let current = object;
+ for (const component of components) {
+ current = current[component];
+ if (current === undefined || current === null) {
+ return defaultValue;
+ }
+ }
+ return current;
+}
+// endregion
+// region Nullability
+/**
+ * Returns a bool indicating whether or not a given object null or undefined.
+ * @param object The object to test.
+ * @return true if the object is null or undefined; false otherwise.
+ */
+export function isNull(object) {
+ return object === null || object === undefined;
+}
+/**
+ * Returns a bool indicating whether or not a given object is null or empty.
+ * @param object The object to test
+ * @return true if object is null or empty; false otherwise.
+ */
+export function isNullOrEmpty(object) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return isNull(object) || Object.keys(object).length === 0;
+}
+/**
+ * Returns a bool indicating whether or not a given object is non-null.
+ * @param object The object to test.
+ * @return true if the object is not null or undefined; false otherwise.
+ */
+export function isDefinedNonNull(object) {
+ return typeof object !== "undefined" && object !== null;
+}
+/**
+ * Returns a bool indicating whether or not a given object is non-null or empty.
+ * @param object The object to test.
+ * @return true if the object is not null or undefined and not empty; false otherwise.
+ */
+export function isDefinedNonNullNonEmpty(object) {
+ if (isNothing(object)) {
+ return false;
+ }
+ if (typeof object === "string") {
+ return object.length > 0;
+ }
+ else if (Array.isArray(object)) {
+ return object.length > 0;
+ }
+ else {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return Object.keys(object).length !== 0;
+ }
+}
+/**
+ * Returns a bool indicating whether or not a given object is non-null or empty.
+ * @param object The object to test.
+ * @return true if the object is not null or undefined and not empty; false otherwise.
+ */
+export function isSetDefinedNonNullNonEmpty(object) {
+ return isDefinedNonNull(object) && object.size > 0;
+}
+/**
+ * Checks if the passed string or number is a number
+ *
+ * @param value The value to check
+ * @return True if the value is an number, false if not
+ */
+export function isNumber(value) {
+ if (isNull(value)) {
+ return false;
+ }
+ let valueToCheck;
+ if (typeof value === "string") {
+ valueToCheck = parseInt(value);
+ }
+ else {
+ valueToCheck = value;
+ }
+ return !Number.isNaN(valueToCheck);
+}
+/**
+ * Checks if the value is a string
+ *
+ * @param value The value to check
+ * @return True if the value is a string, false if not
+ */
+export function isString(value) {
+ if (isNothing(value)) {
+ return false;
+ }
+ return typeof value === "string";
+}
+/**
+ * Returns a bool indicating whether or not a given object is defined but empty.
+ * @param object The object to test.
+ * @return true if the object is not null and empty; false otherwise.
+ */
+export function isArrayDefinedNonNullAndEmpty(object) {
+ return isDefinedNonNull(object) && object.length === 0;
+}
+// endregion
+// region Defaulting Casts
+/**
+ * Check that a given object is an array, substituting an empty array if not.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find an array.
+ * Omit this parameter if `object` is itself an array.
+ * @returns An untyped array.
+ */
+export function asArrayOrEmpty(object, path) {
+ var _a;
+ return (_a = asArray(object, path, [])) !== null && _a !== void 0 ? _a : [];
+}
+/**
+ * Check that a given object is a boolean, substituting the value `false` if not.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a boolean.
+ * Omit this parameter if `object` is itself a boolean.
+ * @returns A boolean from `object`, or defaults to `false`.
+ */
+export function asBooleanOrFalse(object, path) {
+ return asBooleanWithDefault(object, false, path);
+}
+/**
+ * Check that a given object is a boolean, substituting the value `false` if not.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a boolean.
+ * Omit this parameter if `object` is itself a boolean.
+ * @returns A boolean from `object`, or the provided default.
+ */
+export function asBooleanWithDefault(object, defaultValue, path) {
+ const target = traverse(object, path, null);
+ if (typeof target === "boolean") {
+ return target;
+ }
+ else {
+ if (!isNull(target)) {
+ validation.context("asBooleanWithDefault", () => {
+ validation.unexpectedType("defaultValue", "boolean", target, objectPathToString(path));
+ });
+ }
+ return defaultValue;
+ }
+}
+/**
+ * Safely coerce an object into a string.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a string.
+ * Omit this parameter if `object` is itself a string.
+ * @param policy The validation policy to use when resolving this value
+ * @returns A string from `object`, or `null` if `object` is null.
+ */
+export function asString(object, path, policy = "coercible") {
+ const target = traverse(object, path, null);
+ if (isNull(target)) {
+ return target;
+ }
+ else if (typeof target === "string") {
+ return target;
+ }
+ else {
+ // We don't consider arbitrary objects as convertable to strings even through they will result in some value
+ const coercedValue = typeof target === "object" ? null : String(target);
+ switch (policy) {
+ case "strict": {
+ validation.context("asString", () => {
+ validation.unexpectedType("coercedValue", "string", target, objectPathToString(path));
+ });
+ break;
+ }
+ case "coercible": {
+ if (isNull(coercedValue)) {
+ validation.context("asString", () => {
+ validation.unexpectedType("coercedValue", "string", target, objectPathToString(path));
+ });
+ }
+ break;
+ }
+ case "none":
+ default: {
+ break;
+ }
+ }
+ return coercedValue;
+ }
+}
+/**
+ * Safely coerce an object into a number.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a number.
+ * Omit this parameter if `object` is itself a number.
+ * @param policy The validation policy to use when resolving this value
+ * @returns A number from `object`, or `null` if `object` is null.
+ */
+export function asNumber(object, path, policy = "coercible") {
+ const target = traverse(object, path, null);
+ if (isNull(target) || typeof target === "number") {
+ return target;
+ }
+ else {
+ const coercedValue = Number(target);
+ switch (policy) {
+ case "strict": {
+ validation.context("asNumber", () => {
+ validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+ });
+ break;
+ }
+ case "coercible": {
+ if (isNaN(coercedValue)) {
+ validation.context("asNumber", () => {
+ validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+ });
+ return null;
+ }
+ break;
+ }
+ case "none":
+ default: {
+ break;
+ }
+ }
+ return coercedValue;
+ }
+}
+/**
+ * Safely coerce an object into a dictionary.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find the dictionary.
+ * Omit this parameter if `object` is itself a dictionary.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns A sub-dictionary from `object`, or `null` if `object` is null.
+ */
+export function asDictionary(object, path, defaultValue) {
+ const target = traverse(object, path, null);
+ if (target instanceof Object && !Array.isArray(target)) {
+ // Note: It's too expensive to actually validate this is a dictionary of { string : Type } at run time
+ return target;
+ }
+ else {
+ if (!isNull(target)) {
+ validation.context("asDictionary", () => {
+ validation.unexpectedType("defaultValue", "object", target, objectPathToString(path));
+ });
+ }
+ if (isDefinedNonNull(defaultValue)) {
+ return defaultValue;
+ }
+ return null;
+ }
+}
+/**
+ * Coerce an object into an array
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find an array.
+ * Omit this parameter if `object` is itself an array.
+ * @returns An untyped array.
+ */
+export function asArray(object, path, defaultValue) {
+ const target = traverse(object, path, null);
+ if (Array.isArray(target)) {
+ // Note: This is kind of a nasty cast, but I don't think we want to validate that everything is of type T
+ return target;
+ }
+ else {
+ if (!isNull(target)) {
+ validation.context("asArray", () => {
+ validation.unexpectedType("defaultValue", "array", target, objectPathToString(path));
+ });
+ }
+ if (isDefinedNonNull(defaultValue)) {
+ return defaultValue;
+ }
+ return null;
+ }
+}
+/**
+ * Safely coerce an object into a given interface.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a string.
+ * Omit this parameter if `object` is itself a string.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns A sub-dictionary from `object`, or `null` if `object` is null.
+ */
+export function asInterface(object, path, defaultValue) {
+ return asDictionary(object, path, defaultValue);
+}
+/**
+ * Coerce an object into a boolean.
+ * @param object The object to coerce.
+ * @param path The path to traverse on `object` to find a boolean.
+ * Omit this parameter if `object` is itself a boolean.
+ * @param policy The validation policy to use when resolving this value
+ * @returns A boolean from `object`, or `null` if `object` is null.
+ * @note This is distinct from `asBooleanOrFalse` in that it doesn't default to false,
+ * and it tries to convert string boolean values into actual boolean types
+ */
+export function asBoolean(object, path, policy = "coercible") {
+ const target = traverse(object, path, null);
+ // Value was null
+ if (isNull(target)) {
+ return null;
+ }
+ // Value was boolean.
+ if (typeof target === "boolean") {
+ return target;
+ }
+ // Value was string.
+ if (typeof target === "string") {
+ if (target === "true") {
+ return true;
+ }
+ else if (target === "false") {
+ return false;
+ }
+ }
+ // Else coerce.
+ const coercedValue = Boolean(target);
+ switch (policy) {
+ case "strict": {
+ validation.context("asBoolean", () => {
+ validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+ });
+ break;
+ }
+ case "coercible": {
+ if (isNull(coercedValue)) {
+ validation.context("asBoolean", () => {
+ validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+ });
+ return null;
+ }
+ break;
+ }
+ case "none":
+ default: {
+ break;
+ }
+ }
+ return coercedValue;
+}
+/**
+ * Attempts to coerce the passed value to a JSONValue
+ *
+ * Note: due to performance concerns this does not perform a deep inspection of Objects or Arrays.
+ *
+ * @param value The value to coerce
+ * @return A JSONValue or null if value is not a valid JSONValue type
+ */
+export function asJSONValue(value) {
+ if (value === null || value === undefined) {
+ return null;
+ }
+ switch (typeof value) {
+ case "string":
+ case "number":
+ case "boolean":
+ return value;
+ case "object":
+ // Note: It's too expensive to actually validate this is an array of JSONValues at run time
+ if (Array.isArray(value)) {
+ return value;
+ }
+ // Note: It's too expensive to actually validate this is a dictionary of { string : JSONValue } at run time
+ return value;
+ default:
+ validation.context("asJSONValue", () => {
+ validation.unexpectedType("defaultValue", "JSONValue", typeof value);
+ });
+ return null;
+ }
+}
+/**
+ * Attempts to coerce the passed value to JSONData
+ *
+ * @param value The value to coerce
+ * @return A JSONData or null if the value is not a valid JSONData object
+ */
+export function asJSONData(value) {
+ if (value === null || value === undefined) {
+ return null;
+ }
+ if (value instanceof Object && !Array.isArray(value)) {
+ // Note: It's too expensive to actually validate this is a dictionary of { string : Type } at run time
+ return value;
+ }
+ validation.context("asJSONValue", () => {
+ validation.unexpectedType("defaultValue", "object", typeof value);
+ });
+ return null;
+}
+// endregion
+//# sourceMappingURL=server-data.js.map \ No newline at end of file