UNPKG

@wandelbots/nova-js

Version:

Official JS client for the Wandelbots API

1 lines 249 kB
{"version":3,"sources":["../../../src/lib/v1/index.ts","../../../src/lib/v1/ConnectedMotionGroup.ts","../../../src/lib/converters.ts","../../../src/lib/v1/motionStateUpdate.ts","../../../src/lib/v1/getLatestTrajectories.ts","../../../node_modules/lodash-es/_listCacheClear.js","../../../node_modules/lodash-es/eq.js","../../../node_modules/lodash-es/_assocIndexOf.js","../../../node_modules/lodash-es/_listCacheDelete.js","../../../node_modules/lodash-es/_listCacheGet.js","../../../node_modules/lodash-es/_listCacheHas.js","../../../node_modules/lodash-es/_listCacheSet.js","../../../node_modules/lodash-es/_ListCache.js","../../../node_modules/lodash-es/_stackClear.js","../../../node_modules/lodash-es/_stackDelete.js","../../../node_modules/lodash-es/_stackGet.js","../../../node_modules/lodash-es/_stackHas.js","../../../node_modules/lodash-es/_freeGlobal.js","../../../node_modules/lodash-es/_root.js","../../../node_modules/lodash-es/_Symbol.js","../../../node_modules/lodash-es/_getRawTag.js","../../../node_modules/lodash-es/_objectToString.js","../../../node_modules/lodash-es/_baseGetTag.js","../../../node_modules/lodash-es/isObject.js","../../../node_modules/lodash-es/isFunction.js","../../../node_modules/lodash-es/_coreJsData.js","../../../node_modules/lodash-es/_isMasked.js","../../../node_modules/lodash-es/_toSource.js","../../../node_modules/lodash-es/_baseIsNative.js","../../../node_modules/lodash-es/_getValue.js","../../../node_modules/lodash-es/_getNative.js","../../../node_modules/lodash-es/_Map.js","../../../node_modules/lodash-es/_nativeCreate.js","../../../node_modules/lodash-es/_hashClear.js","../../../node_modules/lodash-es/_hashDelete.js","../../../node_modules/lodash-es/_hashGet.js","../../../node_modules/lodash-es/_hashHas.js","../../../node_modules/lodash-es/_hashSet.js","../../../node_modules/lodash-es/_Hash.js","../../../node_modules/lodash-es/_mapCacheClear.js","../../../node_modules/lodash-es/_isKeyable.js","../../../node_modules/lodash-es/_getMapData.js","../../../node_modules/lodash-es/_mapCacheDelete.js","../../../node_modules/lodash-es/_mapCacheGet.js","../../../node_modules/lodash-es/_mapCacheHas.js","../../../node_modules/lodash-es/_mapCacheSet.js","../../../node_modules/lodash-es/_MapCache.js","../../../node_modules/lodash-es/_stackSet.js","../../../node_modules/lodash-es/_Stack.js","../../../node_modules/lodash-es/_setCacheAdd.js","../../../node_modules/lodash-es/_setCacheHas.js","../../../node_modules/lodash-es/_SetCache.js","../../../node_modules/lodash-es/_arraySome.js","../../../node_modules/lodash-es/_cacheHas.js","../../../node_modules/lodash-es/_equalArrays.js","../../../node_modules/lodash-es/_Uint8Array.js","../../../node_modules/lodash-es/_mapToArray.js","../../../node_modules/lodash-es/_setToArray.js","../../../node_modules/lodash-es/_equalByTag.js","../../../node_modules/lodash-es/_arrayPush.js","../../../node_modules/lodash-es/isArray.js","../../../node_modules/lodash-es/_baseGetAllKeys.js","../../../node_modules/lodash-es/_arrayFilter.js","../../../node_modules/lodash-es/stubArray.js","../../../node_modules/lodash-es/_getSymbols.js","../../../node_modules/lodash-es/_baseTimes.js","../../../node_modules/lodash-es/isObjectLike.js","../../../node_modules/lodash-es/_baseIsArguments.js","../../../node_modules/lodash-es/isArguments.js","../../../node_modules/lodash-es/stubFalse.js","../../../node_modules/lodash-es/isBuffer.js","../../../node_modules/lodash-es/_isIndex.js","../../../node_modules/lodash-es/isLength.js","../../../node_modules/lodash-es/_baseIsTypedArray.js","../../../node_modules/lodash-es/_baseUnary.js","../../../node_modules/lodash-es/_nodeUtil.js","../../../node_modules/lodash-es/isTypedArray.js","../../../node_modules/lodash-es/_arrayLikeKeys.js","../../../node_modules/lodash-es/_isPrototype.js","../../../node_modules/lodash-es/_overArg.js","../../../node_modules/lodash-es/_nativeKeys.js","../../../node_modules/lodash-es/_baseKeys.js","../../../node_modules/lodash-es/isArrayLike.js","../../../node_modules/lodash-es/keys.js","../../../node_modules/lodash-es/_getAllKeys.js","../../../node_modules/lodash-es/_equalObjects.js","../../../node_modules/lodash-es/_DataView.js","../../../node_modules/lodash-es/_Promise.js","../../../node_modules/lodash-es/_Set.js","../../../node_modules/lodash-es/_WeakMap.js","../../../node_modules/lodash-es/_getTag.js","../../../node_modules/lodash-es/_baseIsEqualDeep.js","../../../node_modules/lodash-es/_baseIsEqual.js","../../../node_modules/lodash-es/isEqual.js","../../../src/lib/v1/JoggerConnection.ts","../../../src/lib/v1/MotionStreamConnection.ts","../../../src/lib/v1/NovaCellAPIClient.ts","../../../src/lib/v1/NovaClient.ts","../../../src/LoginWithAuth0.ts","../../../src/lib/AutoReconnectingWebsocket.ts","../../../src/lib/availableStorage.ts","../../../src/lib/v1/mock/MockNovaInstance.ts","../../../src/lib/v1/ProgramStateConnection.ts"],"sourcesContent":["export * from \"@wandelbots/nova-api/v1\"\nexport * from \"./ConnectedMotionGroup\"\nexport * from \"./getLatestTrajectories\"\nexport * from \"./JoggerConnection\"\nexport * from \"./MotionStreamConnection\"\nexport * from \"./NovaCellAPIClient\"\nexport * from \"./NovaClient\"\nexport * from \"./ProgramStateConnection\"\n","import type {\n ControllerInstance,\n MotionGroupPhysical,\n MotionGroupSpecification,\n MotionGroupStateResponse,\n Mounting,\n RobotControllerState,\n RobotControllerStateOperationModeEnum,\n RobotControllerStateSafetyStateEnum,\n RobotTcp,\n SafetySetup,\n} from \"@wandelbots/nova-api/v1\"\nimport { makeAutoObservable, runInAction } from \"mobx\"\nimport * as THREE from \"three\"\nimport type { AutoReconnectingWebsocket } from \"../AutoReconnectingWebsocket\"\nimport { tryParseJson } from \"../converters\"\nimport { jointValuesEqual, tcpPoseEqual } from \"./motionStateUpdate\"\nimport type { NovaClient } from \"./NovaClient\"\n\nconst MOTION_DELTA_THRESHOLD = 0.0001\n\nexport type MotionGroupOption = {\n selectionId: string\n} & MotionGroupPhysical\n\n/**\n * Store representing the current state of a connected motion group.\n */\nexport class ConnectedMotionGroup {\n static async connect(\n nova: NovaClient,\n motionGroupId: string,\n controllers: ControllerInstance[],\n ) {\n const [_motionGroupIndex, controllerId] = motionGroupId.split(\"@\") as [\n string,\n string,\n ]\n const controller = controllers.find((c) => c.controller === controllerId)\n const motionGroup = controller?.physical_motion_groups.find(\n (mg) => mg.motion_group === motionGroupId,\n )\n if (!controller || !motionGroup) {\n throw new Error(\n `Controller ${controllerId} or motion group ${motionGroupId} not found`,\n )\n }\n\n const motionStateSocket = nova.openReconnectingWebsocket(\n `/motion-groups/${motionGroupId}/state-stream`,\n )\n\n // Wait for the first message to get the initial state\n const firstMessage = await motionStateSocket.firstMessage()\n const initialMotionState = tryParseJson(firstMessage.data)\n ?.result as MotionGroupStateResponse\n\n if (!initialMotionState) {\n throw new Error(\n `Unable to parse initial motion state message ${firstMessage.data}`,\n )\n }\n\n console.log(\n `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\\n `,\n initialMotionState,\n )\n\n // Check if robot is virtual or physical\n const config = await nova.api.controller.getRobotController(\n controller.controller,\n )\n const isVirtual = config.configuration.kind === \"VirtualController\"\n\n // If there's a configured mounting, we need it to show the right\n // position of the robot model\n const mounting = await (async () => {\n try {\n const mounting = await nova.api.motionGroupInfos.getMounting(\n motionGroup.motion_group,\n )\n return mounting\n } catch (err) {\n console.error(\n `Error fetching mounting for ${motionGroup.motion_group}`,\n err,\n )\n return null\n }\n })()\n\n // Open the websocket to monitor controller state for e.g. e-stop\n const controllerStateSocket = nova.openReconnectingWebsocket(\n `/controllers/${controller.controller}/state-stream?response_rate=1000`,\n )\n\n // Wait for the first message to get the initial state\n const firstControllerMessage = await controllerStateSocket.firstMessage()\n const initialControllerState = tryParseJson(firstControllerMessage.data)\n ?.result as RobotControllerState\n\n if (!initialControllerState) {\n throw new Error(\n `Unable to parse initial controller state message ${firstControllerMessage.data}`,\n )\n }\n\n console.log(\n `Connected controller state websocket to controller ${controller.controller}. Initial state:\\n `,\n initialControllerState,\n )\n\n // Find out what TCPs this motion group has (we need it for jogging)\n const { tcps } = await nova.api.motionGroupInfos.listTcps(motionGroupId)\n\n const motionGroupSpecification =\n await nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId)\n\n const safetySetup =\n await nova.api.motionGroupInfos.getSafetySetup(motionGroupId)\n\n return new ConnectedMotionGroup(\n nova,\n controller,\n motionGroup,\n initialMotionState,\n motionStateSocket,\n isVirtual,\n tcps!,\n motionGroupSpecification,\n safetySetup,\n mounting,\n initialControllerState,\n controllerStateSocket,\n )\n }\n\n connectedJoggingCartesianSocket: WebSocket | null = null\n connectedJoggingJointsSocket: WebSocket | null = null\n planData: any | null // tmp\n joggingVelocity: number = 10\n\n // Not mobx-observable as this changes very fast; should be observed\n // using animation frames\n rapidlyChangingMotionState: MotionGroupStateResponse\n\n // Response rate on the websocket should be a bit slower on this one since\n // we don't use the motion data\n controllerState: RobotControllerState\n\n /**\n * Reflects activation state of the motion group / robot servos. The\n * movement controls in the UI should only be enabled in the \"active\" state\n */\n activationState: \"inactive\" | \"activating\" | \"deactivating\" | \"active\" =\n \"inactive\"\n\n constructor(\n readonly nova: NovaClient,\n readonly controller: ControllerInstance,\n readonly motionGroup: MotionGroupPhysical,\n readonly initialMotionState: MotionGroupStateResponse,\n readonly motionStateSocket: AutoReconnectingWebsocket,\n readonly isVirtual: boolean,\n readonly tcps: RobotTcp[],\n readonly motionGroupSpecification: MotionGroupSpecification,\n readonly safetySetup: SafetySetup,\n readonly mounting: Mounting | null,\n readonly initialControllerState: RobotControllerState,\n readonly controllerStateSocket: AutoReconnectingWebsocket,\n ) {\n this.rapidlyChangingMotionState = initialMotionState\n this.controllerState = initialControllerState\n\n // Track controller state updates (e.g. safety state and operation mode)\n controllerStateSocket.addEventListener(\"message\", (event) => {\n const data = tryParseJson(event.data)?.result\n\n if (!data) {\n return\n }\n\n runInAction(() => {\n this.controllerState = data\n })\n })\n\n motionStateSocket.addEventListener(\"message\", (event) => {\n const motionStateResponse = tryParseJson(event.data)?.result as\n | MotionGroupStateResponse\n | undefined\n\n if (!motionStateResponse) {\n throw new Error(\n `Failed to get motion state for ${this.motionGroupId}: ${event.data}`,\n )\n }\n\n // handle motionState message\n if (\n !jointValuesEqual(\n this.rapidlyChangingMotionState.state.joint_position.joints,\n motionStateResponse.state.joint_position.joints,\n MOTION_DELTA_THRESHOLD,\n )\n ) {\n runInAction(() => {\n this.rapidlyChangingMotionState.state = motionStateResponse.state\n })\n }\n\n // handle tcpPose message\n if (\n !tcpPoseEqual(\n this.rapidlyChangingMotionState.tcp_pose,\n motionStateResponse.tcp_pose,\n MOTION_DELTA_THRESHOLD,\n )\n ) {\n runInAction(() => {\n this.rapidlyChangingMotionState.tcp_pose =\n motionStateResponse.tcp_pose\n })\n }\n })\n makeAutoObservable(this)\n }\n\n get motionGroupId() {\n return this.motionGroup.motion_group\n }\n\n get controllerId() {\n return this.controller.controller\n }\n\n get modelFromController() {\n return this.motionGroup.model_from_controller\n }\n\n get wandelscriptIdentifier() {\n const num = this.motionGroupId.split(\"@\")[0]\n return `${this.controllerId.replaceAll(\"-\", \"_\")}_${num}`\n }\n\n /** Jogging velocity in radians for rotation and joint movement */\n get joggingVelocityRads() {\n return (this.joggingVelocity * Math.PI) / 180\n }\n\n get joints() {\n return this.initialMotionState.state.joint_position.joints.map((_, i) => {\n return {\n index: i,\n }\n })\n }\n\n get dhParameters() {\n return this.motionGroupSpecification.dh_parameters\n }\n\n get safetyZones() {\n return this.safetySetup.safety_zones\n }\n\n /** Gets the robot mounting position offset in 3D viz coordinates */\n get mountingPosition(): [number, number, number] {\n if (!this.mounting) {\n return [0, 0, 0]\n }\n\n return [\n this.mounting.pose.position.x / 1000,\n this.mounting.pose.position.y / 1000,\n this.mounting.pose.position.z / 1000,\n ]\n }\n\n /** Gets the robot mounting position rotation in 3D viz coordinates */\n get mountingQuaternion() {\n const rotationVector = new THREE.Vector3(\n this.mounting?.pose.orientation?.x || 0,\n this.mounting?.pose.orientation?.y || 0,\n this.mounting?.pose.orientation?.z || 0,\n )\n\n const magnitude = rotationVector.length()\n const axis = rotationVector.normalize()\n\n return new THREE.Quaternion().setFromAxisAngle(axis, magnitude)\n }\n\n /**\n * Whether the controller is currently in a safety state\n * corresponding to an emergency stop\n */\n get isEstopActive() {\n const estopStates: RobotControllerStateSafetyStateEnum[] = [\n \"SAFETY_STATE_ROBOT_EMERGENCY_STOP\",\n \"SAFETY_STATE_DEVICE_EMERGENCY_STOP\",\n ]\n\n return estopStates.includes(this.controllerState.safety_state)\n }\n\n /**\n * Whether the controller is in a safety state\n * that may be non-functional for robot pad purposes\n */\n get isMoveableSafetyState() {\n const goodSafetyStates: RobotControllerStateSafetyStateEnum[] = [\n \"SAFETY_STATE_NORMAL\",\n \"SAFETY_STATE_REDUCED\",\n ]\n\n return goodSafetyStates.includes(this.controllerState.safety_state)\n }\n\n /**\n * Whether the controller is in an operation mode that allows movement\n */\n get isMoveableOperationMode() {\n const goodOperationModes: RobotControllerStateOperationModeEnum[] = [\n \"OPERATION_MODE_AUTO\",\n \"OPERATION_MODE_MANUAL\",\n \"OPERATION_MODE_MANUAL_T1\",\n \"OPERATION_MODE_MANUAL_T2\",\n ]\n\n return goodOperationModes.includes(this.controllerState.operation_mode)\n }\n\n /**\n * Whether the robot is currently active and can be moved, based on the\n * safety state, operation mode and servo toggle activation state.\n */\n get canBeMoved() {\n return (\n this.isMoveableSafetyState &&\n this.isMoveableOperationMode &&\n this.activationState === \"active\"\n )\n }\n\n async deactivate() {\n if (this.activationState !== \"active\") {\n console.error(\"Tried to deactivate while already deactivating\")\n return\n }\n\n runInAction(() => {\n this.activationState = \"deactivating\"\n })\n\n try {\n await this.nova.api.controller.setDefaultMode(\n this.controllerId,\n \"MODE_MONITOR\",\n )\n\n runInAction(() => {\n this.activationState = \"inactive\"\n })\n } catch (err) {\n runInAction(() => {\n this.activationState = \"active\"\n })\n throw err\n }\n }\n\n async activate() {\n if (this.activationState !== \"inactive\") {\n console.error(\"Tried to activate while already activating\")\n return\n }\n\n runInAction(() => {\n this.activationState = \"activating\"\n })\n\n try {\n await this.nova.api.controller.setDefaultMode(\n this.controllerId,\n \"MODE_CONTROL\",\n )\n\n runInAction(() => {\n this.activationState = \"active\"\n })\n } catch (err) {\n runInAction(() => {\n this.activationState = \"inactive\"\n })\n throw err\n }\n }\n\n toggleActivation() {\n if (this.activationState === \"inactive\") {\n this.activate()\n } else if (this.activationState === \"active\") {\n this.deactivate()\n }\n }\n\n dispose() {\n this.motionStateSocket.close()\n if (this.connectedJoggingCartesianSocket)\n this.connectedJoggingCartesianSocket.close()\n if (this.connectedJoggingJointsSocket)\n this.connectedJoggingJointsSocket.close()\n }\n\n setJoggingVelocity(velocity: number) {\n this.joggingVelocity = velocity\n }\n}\n","import type { Pose } from \"@wandelbots/nova-api/v1\"\n\n/** Try to parse something as JSON; return undefined if we can't */\nexport function tryParseJson(json: unknown): any {\n try {\n return JSON.parse(json as string)\n } catch {\n return undefined\n }\n}\n\n/** Try to turn something into JSON; return undefined if we can't */\nexport function tryStringifyJson(json: unknown): string | undefined {\n try {\n return JSON.stringify(json)\n } catch {\n return undefined\n }\n}\n\n/**\n * Converts object parameters to query string.\n * e.g. { a: \"1\", b: \"2\" } => \"?a=1&b=2\"\n * {} => \"\"\n */\nexport function makeUrlQueryString(obj: Record<string, string>): string {\n const str = new URLSearchParams(obj).toString()\n return str ? `?${str}` : \"\"\n}\n\n/** Convert radians to degrees */\nexport function radiansToDegrees(radians: number): number {\n return radians * (180 / Math.PI)\n}\n\n/** Convert degrees to radians */\nexport function degreesToRadians(degrees: number): number {\n return degrees * (Math.PI / 180)\n}\n\n/**\n * Convert a Pose object representing a motion group position\n * into a string which represents that pose in Wandelscript.\n */\nexport function poseToWandelscriptString(\n pose: Pick<Pose, \"position\" | \"orientation\">,\n) {\n const position = [pose.position.x, pose.position.y, pose.position.z]\n const orientation = [\n pose.orientation?.x ?? 0,\n pose.orientation?.y ?? 0,\n pose.orientation?.z ?? 0,\n ]\n\n const positionValues = position.map((v) => v.toFixed(1))\n // Rotation needs more precision since it's in radians\n const rotationValues = orientation.map((v) => v.toFixed(4))\n\n return `(${positionValues.concat(rotationValues).join(\", \")})`\n}\n\n/**\n * Check for coordinate system id equivalence, accounting for the \"world\" default\n * on empty/undefined values.\n */\nexport function isSameCoordinateSystem(\n firstCoordSystem: string | undefined,\n secondCoordSystem: string | undefined,\n) {\n if (!firstCoordSystem) firstCoordSystem = \"world\"\n if (!secondCoordSystem) secondCoordSystem = \"world\"\n\n return firstCoordSystem === secondCoordSystem\n}\n","import type { TcpPose } from \"@wandelbots/nova-api/v1\"\n\nexport function jointValuesEqual(\n oldJointValues: number[],\n newJointValues: number[],\n changeDeltaThreshold: number,\n): boolean {\n if (newJointValues.length !== oldJointValues.length) {\n return true\n }\n\n for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) {\n if (\n Math.abs(newJointValues[jointIndex]! - oldJointValues[jointIndex]!) >\n changeDeltaThreshold\n ) {\n return false\n }\n }\n\n return true\n}\n\nexport function tcpPoseEqual(\n oldTcp: TcpPose | undefined,\n newTcp: TcpPose | undefined,\n changeDeltaThreshold: number,\n): boolean {\n // undefined -> defined (+reverse) transition\n if ((oldTcp === undefined && newTcp) || (oldTcp && newTcp === undefined)) {\n return false\n }\n\n // the typechecker cannot resolve states to \"!= undefined\" if \"&&\" is used\n if (oldTcp === undefined || newTcp === undefined) {\n return true\n }\n\n let changedDelta = 0\n changedDelta += Math.abs(oldTcp.orientation.x - newTcp.orientation.x)\n changedDelta += Math.abs(oldTcp.orientation.y - newTcp.orientation.y)\n changedDelta += Math.abs(oldTcp.orientation.z - newTcp.orientation.z)\n changedDelta += Math.abs(oldTcp.position.x - newTcp.position.x)\n changedDelta += Math.abs(oldTcp.position.y - newTcp.position.y)\n changedDelta += Math.abs(oldTcp.position.z - newTcp.position.z)\n\n if (changedDelta > changeDeltaThreshold) {\n return false\n }\n\n return (\n oldTcp.coordinate_system === newTcp.coordinate_system &&\n oldTcp.tcp === newTcp.tcp\n )\n}\n","import type { GetTrajectoryResponse } from \"@wandelbots/nova-api/v1\"\nimport type { NovaCellAPIClient } from \"./NovaCellAPIClient\"\n\nlet lastMotionIds: Set<string> = new Set()\n\nexport async function getLatestTrajectories(\n apiClient: NovaCellAPIClient,\n sampleTime: number = 50,\n responsesCoordinateSystem?: string,\n): Promise<GetTrajectoryResponse[]> {\n const newTrajectories: GetTrajectoryResponse[] = []\n\n try {\n const motions = await apiClient.motion.listMotions()\n const currentMotionIds = new Set(motions.motions)\n\n const newMotionIds = Array.from(currentMotionIds).filter(\n (id) => !lastMotionIds.has(id),\n )\n\n for (const motionId of newMotionIds) {\n const trajectory = await apiClient.motion.getMotionTrajectory(\n motionId,\n sampleTime,\n responsesCoordinateSystem,\n )\n newTrajectories.push(trajectory)\n }\n\n lastMotionIds = currentMotionIds\n } catch (error) {\n console.error(\"Failed to get latest trajectories:\", error)\n }\n\n return newTrajectories\n}\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nexport default listCacheDelete;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nexport default listCacheSet;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nexport default hashSet;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nexport default mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nexport default getMapData;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nexport default mapCacheSet;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nexport default stackSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfun