UNPKG

pncat

Version:

A unified cli tool that enhances package managers catalogs feature.

1,625 lines (1,616 loc) 73.8 kB
import { a as __toESM, t as __commonJSMin } from "./chunk-6qLfnLNH.mjs"; import { t as require_semver } from "./semver-Df1PSY8l.mjs"; import { readFile, writeFile } from "node:fs/promises"; import { dirname, join, resolve } from "pathe"; import process from "node:process"; import { findUp } from "find-up-simple"; import * as p from "@clack/prompts"; import c from "ansis"; import { parsePnpmWorkspaceYaml } from "pnpm-workspace-yaml"; //#region package.json var name = "pncat"; var version = "0.7.7"; //#endregion //#region src/constants.ts const NAME = name; const VERSION = version; const MODE_CHOICES = [ "init", "detect", "migrate", "add", "remove", "clean", "revert" ]; const MODE_ALIASES = { init: [ "create", "setup", "config", "conf" ], detect: [ "scan", "check", "find", "d" ], migrate: [ "move", "mv", "mig", "m" ], add: [ "install", "in", "i" ], remove: [ "uninstall", "rm", "r", "un", "u" ], clean: [ "prune", "cl", "c" ], revert: [ "restore", "undo", "rev" ] }; const AGENTS = [ "pnpm", "yarn", "bun", "vlt" ]; const AGENT_CONFIG = { pnpm: { type: "pnpm-workspace.yaml", depType: "pnpm-workspace", filename: "pnpm-workspace.yaml", locks: "pnpm-lock.yaml", defaultContent: "packages: []" }, yarn: { type: ".yarnrc.yml", depType: "yarn-workspace", filename: ".yarnrc.yml", locks: "yarn.lock", defaultContent: "defaultProtocol: \"npm:\"" }, bun: { type: "bun-workspace", depType: "bun-workspace", filename: "package.json", locks: ["bun.lockb", "bun.lock"], defaultContent: "" }, vlt: { type: "vlt.json", depType: "vlt-workspace", filename: "vlt.json", locks: "vlt-lock.json", defaultContent: "{}" } }; const CMD_BOOL_FLAGS = new Set([ "save-dev", "save-peer", "save-optional", "save-exact", "recursive" ]); const CMD_BOOL_SHORT_FLAGS = new Set([ "D", "P", "O", "E", "r" ]); const DEFAULT_CATALOG_OPTIONS = { mode: "detect", recursive: true, force: false, ignoreOtherWorkspaces: true, depFields: { "dependencies": true, "devDependencies": true, "peerDependencies": true, "optionalDependencies": true, "resolutions": true, "overrides": true, "pnpm.overrides": true }, allowedProtocols: [ "workspace", "link", "file" ], specifierOptions: { skipComplexRanges: true, allowPreReleases: true, allowWildcards: false }, yes: false, saveExact: false, install: true }; const DEFAULT_IGNORE_PATHS = [ "**/node_modules/**", "**/dist/**", "**/public/**", "**/fixture/**", "**/fixtures/**" ]; const COMMON_DEPS_FIELDS = [ "dependencies", "devDependencies", "peerDependencies", "optionalDependencies" ]; const DEPS_FIELDS = [ ...COMMON_DEPS_FIELDS, "pnpm.overrides", "resolutions", "overrides", "pnpm-workspace", "yarn-workspace", "bun-workspace", "vlt-workspace" ]; const DEPS_TYPE_SHORT_MAP = { "dependencies": "", "devDependencies": "dev", "peerDependencies": "peer", "optionalDependencies": "optional", "resolutions": "resolutions", "overrides": "overrides", "pnpm.overrides": "pnpm-overrides", "pnpm-workspace": "pnpm-workspace", "yarn-workspace": "yarn-workspace", "bun-workspace": "bun-workspace", "vlt-workspace": "vlt-workspace" }; const DEPS_TYPE_CATALOG_MAP = { dependencies: "prod", devDependencies: "dev", peerDependencies: "peer", optionalDependencies: "optional" }; //#endregion //#region src/utils/specifier.ts var import_semver$1 = require_semver(); function parseSpec(spec) { let name$1; let specifier; const parts = spec.split(/@/g); if (parts[0] === "") { name$1 = parts.slice(0, 2).join("@"); specifier = parts[2]; } else { name$1 = parts[0]; specifier = parts[1]; } return { name: name$1, specifier }; } function cleanSpec(spec, options) { if (options?.allowedProtocols?.some((p$1) => spec.startsWith(p$1))) return null; const version$1 = (0, import_semver$1.valid)((0, import_semver$1.clean)(spec)); if (version$1) return version$1; const coerced = (0, import_semver$1.coerce)(spec); if (coerced) return coerced.version; return null; } function sortSpecs(specs, options) { return specs.sort((a, b) => { const ver1 = cleanSpec(a, options); const ver2 = cleanSpec(b, options); if (ver1 && ver2) return (0, import_semver$1.gt)(ver1, ver2) ? -1 : 1; return 0; }); } function mostSpecificRule(matchingRules) { if (!matchingRules.length) return matchingRules[0]; return matchingRules.reduce((mostSpecific, current) => { if ((0, import_semver$1.subset)(current.specifier, mostSpecific.specifier)) return current; if ((0, import_semver$1.subset)(mostSpecific.specifier, current.specifier)) return mostSpecific; const minVer1 = (0, import_semver$1.minVersion)(mostSpecific.specifier); const minVer2 = (0, import_semver$1.minVersion)(current.specifier); if (minVer1 && minVer2) { if ((0, import_semver$1.gt)(minVer1, minVer2)) return mostSpecific; return current; } return mostSpecific; }); } //#endregion //#region src/utils/catalog.ts var import_semver = require_semver(); function isCatalogWorkspace(type) { return type === "pnpm-workspace" || type === "yarn-workspace" || type === "bun-workspace" || type === "vlt-workspace"; } function isCatalogPackageName(name$1) { if (!name$1) return false; return name$1.startsWith("pnpm-catalog:") || name$1.startsWith("yarn-catalog:") || name$1.startsWith("bun-catalog:") || name$1.startsWith("vlt-catalog:"); } function extractCatalogName(name$1) { return name$1.replace("pnpm-catalog:", "").replace("yarn-catalog:", "").replace("bun-catalog:", "").replace("vlt-catalog:", ""); } function isCatalogSpecifier(specifier) { return specifier.startsWith("catalog:"); } function normalizeCatalogName(catalogName) { return catalogName === "default" ? "catalog:" : `catalog:${catalogName}`; } function isDepMatched(depName, match) { if (Array.isArray(match)) return match.some((m) => typeof m === "string" ? depName === m : m.test(depName)); else if (typeof match === "string") return depName === match; else if (match instanceof RegExp) return match.test(depName); return false; } function inferCatalogName(dep, options) { for (const rule of options.catalogRules ?? []) { const { name: name$1, match, specifierRules } = rule; if (!isDepMatched(dep.name, match)) continue; if (!specifierRules?.length) return name$1; const version$1 = cleanSpec(dep.specifier, options); if (!version$1) return name$1; const matchingRules = specifierRules.filter((specifierRule) => { if (specifierRule.match && !isDepMatched(dep.name, specifierRule.match)) return false; return (0, import_semver.satisfies)(version$1, specifierRule.specifier); }); if (matchingRules.length === 0) return name$1; if (matchingRules.length === 1) { const rule$1 = matchingRules[0]; return rule$1.name || `${name$1}-${rule$1.suffix}`; } const bestMatching = mostSpecificRule(matchingRules); return bestMatching.name || `${name$1}-${bestMatching.suffix}`; } return DEPS_TYPE_CATALOG_MAP[dep.source] || "default"; } function createDepCatalogIndex(workspaceJson) { const catalogIndex = /* @__PURE__ */ new Map(); if (!workspaceJson) return catalogIndex; if (workspaceJson.catalog) for (const [depName, specifier] of Object.entries(workspaceJson.catalog)) { if (!catalogIndex.has(depName)) catalogIndex.set(depName, []); catalogIndex.get(depName)?.push({ catalogName: "default", specifier }); } if (workspaceJson.catalogs) { for (const [catalogName, catalog] of Object.entries(workspaceJson.catalogs)) if (catalog) for (const [depName, specifier] of Object.entries(catalog)) { if (!catalogIndex.has(depName)) catalogIndex.set(depName, []); catalogIndex.get(depName)?.push({ catalogName, specifier }); } } return catalogIndex; } //#endregion //#region src/utils/helper.ts function getDepSource(isDev = false, isOptional = false, isPeer = false) { return isDev ? "devDependencies" : isOptional ? "optionalDependencies" : isPeer ? "peerDependencies" : "dependencies"; } function isPnpmOverridesPackageName(pkgName) { return pkgName === "pnpm-workspace:overrides"; } async function updatePackageToCatalog(dep, data, workspace) { if (dep.source === "pnpm.overrides") { data.raw.pnpm.overrides[dep.name] = normalizeCatalogName(dep.catalogName); return; } if (dep.source === "pnpm-workspace") { await workspace.catalog.setPackage(normalizeCatalogName(dep.catalogName), dep.name, dep.specifier); return; } data.raw[dep.source][dep.name] = normalizeCatalogName(dep.catalogName); } async function updatePackageToSpecifier(dep, data) { if (dep.source === "pnpm.overrides") { data.raw.pnpm.overrides[dep.name] = dep.specifier; return; } data.raw[dep.source][dep.name] = dep.specifier; } function containsESLint(packages) { for (const pkg of packages) if (pkg.type === "package.json") { if (pkg.deps.find((i) => i.name === "eslint")) return true; } return false; } function containsVSCodeExtension(packages) { for (const pkg of packages) if (pkg.type === "package.json") { const { vscode } = pkg.raw.engines ?? {}; if (vscode) return true; } return false; } //#endregion //#region src/io/dependencies.ts function flatten(obj, parents = []) { if (!obj) return obj; let flattenData = {}; for (const [key, value] of Object.entries(obj)) if (typeof value === "object") flattenData = { ...flattenData, ...flatten(value, [...parents, key]) }; else if (typeof value === "string") flattenData[key] = { specifier: value, parents }; return flattenData; } function getByPath(obj, path) { return flatten(path.split(".").reduce((o, i) => o?.[i], obj)); } function parseDependency(name$1, specifier, type, shouldCatalog, options, parents, packageName) { const dep = { name: name$1, specifier, parents, source: type, catalog: isCatalogWorkspace(type) || isCatalogSpecifier(specifier), catalogable: shouldCatalog(name$1, specifier) }; return { ...dep, catalogName: isCatalogWorkspace(type) && !isPnpmOverridesPackageName(packageName) ? extractCatalogName(packageName) : inferCatalogName(dep, options) }; } function parseDependencies(pkg, type, shouldCatalog, options) { return Object.entries(getByPath(pkg, type) || {}).map(([name$1, { specifier, parents }]) => parseDependency(name$1, specifier, type, shouldCatalog, options, parents)); } //#endregion //#region node_modules/.pnpm/@antfu+utils@9.3.0/node_modules/@antfu/utils/dist/index.mjs function toArray(array) { array = array ?? []; return Array.isArray(array) ? array : [array]; } //#endregion //#region src/io/workspace.ts async function detectWorkspaceRoot(agent = "pnpm") { const root$1 = await findUp(".git", { cwd: process.cwd() }); if (root$1) return dirname(root$1); for (const lock of toArray(AGENT_CONFIG[agent].locks)) { const filepath = await findUp(lock, { cwd: process.cwd() }); if (filepath) return dirname(filepath); } return process.cwd(); } //#endregion //#region node_modules/.pnpm/lodash.clonedeep@4.5.0/node_modules/lodash.clonedeep/index.js var require_lodash = /* @__PURE__ */ __commonJSMin(((exports, module) => { /** * lodash (Custom Build) <https://lodash.com/> * Build: `lodash modularize exports="npm" -o ./` * Copyright jQuery Foundation and other contributors <https://jquery.org/> * Released under MIT license <https://lodash.com/license> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = "__lodash_hash_undefined__"; /** Used as references for various `Number` constants. */ var MAX_SAFE_INTEGER = 9007199254740991; /** `Object#toString` result references. */ var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", promiseTag = "[object Promise]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", weakMapTag = "[object WeakMap]"; var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; /** * Used to match `RegExp` * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; /** Used to detect host constructors (Safari). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; /** Detect free variable `global` from Node.js. */ var freeGlobal = typeof global == "object" && global && global.Object === Object && global; /** Detect free variable `self`. */ var freeSelf = typeof self == "object" && self && self.Object === Object && self; /** Used as a reference to the global object. */ var root = freeGlobal || freeSelf || Function("return this")(); /** Detect free variable `exports`. */ var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; /** Detect free variable `module`. */ var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports; /** * Adds the key-value `pair` to `map`. * * @private * @param {Object} map The map to modify. * @param {Array} pair The key-value pair to add. * @returns {Object} Returns `map`. */ function addMapEntry(map, pair) { map.set(pair[0], pair[1]); return map; } /** * Adds `value` to `set`. * * @private * @param {Object} set The set to modify. * @param {*} value The value to add. * @returns {Object} Returns `set`. */ function addSetEntry(set, value) { set.add(value); return set; } /** * A specialized version of `_.forEach` for arrays without support for * iteratee shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array ? array.length : 0; while (++index < length) if (iteratee(array[index], index, array) === false) break; return array; } /** * Appends the elements of `values` to `array`. * * @private * @param {Array} array The array to modify. * @param {Array} values The values to append. * @returns {Array} Returns `array`. */ function arrayPush(array, values) { var index = -1, length = values.length, offset = array.length; while (++index < length) array[offset + index] = values[index]; return array; } /** * A specialized version of `_.reduce` for arrays without support for * iteratee shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initAccum] Specify using the first element of `array` as * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, length = array ? array.length : 0; if (initAccum && length) accumulator = array[++index]; while (++index < length) accumulator = iteratee(accumulator, array[index], index, array); return accumulator; } /** * The base implementation of `_.times` without support for iteratee shorthands * or max array length checks. * * @private * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the array of results. */ function baseTimes(n, iteratee) { var index = -1, result = Array(n); while (++index < n) result[index] = iteratee(index); return result; } /** * Gets the value at `key` of `object`. * * @private * @param {Object} [object] The object to query. * @param {string} key The key of the property to get. * @returns {*} Returns the property value. */ function getValue(object, key) { return object == null ? void 0 : object[key]; } /** * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ function isHostObject(value) { var result = false; if (value != null && typeof value.toString != "function") try { result = !!(value + ""); } catch (e) {} return result; } /** * Converts `map` to its key-value pairs. * * @private * @param {Object} map The map to convert. * @returns {Array} Returns the key-value pairs. */ function mapToArray(map) { var index = -1, result = Array(map.size); map.forEach(function(value, key) { result[++index] = [key, value]; }); return result; } /** * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. * @param {Function} transform The argument transform. * @returns {Function} Returns the new function. */ function overArg(func, transform) { return function(arg) { return func(transform(arg)); }; } /** * Converts `set` to an array of its values. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the values. */ function setToArray(set) { var index = -1, result = Array(set.size); set.forEach(function(value) { result[++index] = value; }); return result; } /** Used for built-in method references. */ var arrayProto = Array.prototype, funcProto = Function.prototype, objectProto = Object.prototype; /** Used to detect overreaching core-js shims. */ var coreJsData = root["__core-js_shared__"]; /** Used to detect methods masquerading as native. */ var maskSrcKey = function() { var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ""); return uid ? "Symbol(src)_1." + uid : ""; }(); /** Used to resolve the decompiled source of functions. */ var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /** Used to detect if a method is native. */ var reIsNative = RegExp("^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); /** Built-in value references. */ var Buffer = moduleExports ? root.Buffer : void 0, Symbol$1 = root.Symbol, Uint8Array = root.Uint8Array, getPrototype = overArg(Object.getPrototypeOf, Object), objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice; var nativeGetSymbols = Object.getOwnPropertySymbols, nativeIsBuffer = Buffer ? Buffer.isBuffer : void 0, nativeKeys = overArg(Object.keys, Object); var DataView = getNative(root, "DataView"), Map$1 = getNative(root, "Map"), Promise$1 = getNative(root, "Promise"), Set$1 = getNative(root, "Set"), WeakMap$1 = getNative(root, "WeakMap"), nativeCreate = getNative(Object, "create"); /** Used to detect maps, sets, and weakmaps. */ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap$1); /** Used to convert symbols to primitives and strings. */ var symbolProto = Symbol$1 ? Symbol$1.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0; /** * Creates a hash object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Hash(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the hash. * * @private * @name clear * @memberOf Hash */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; } /** * Removes `key` and its value from the hash. * * @private * @name delete * @memberOf Hash * @param {Object} hash The hash to modify. * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { return this.has(key) && delete this.__data__[key]; } /** * Gets the hash value for `key`. * * @private * @name get * @memberOf Hash * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function hashGet(key) { var data = this.__data__; if (nativeCreate) { var result = data[key]; return result === HASH_UNDEFINED ? void 0 : result; } return hasOwnProperty.call(data, key) ? data[key] : void 0; } /** * Checks if a hash value for `key` exists. * * @private * @name has * @memberOf Hash * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function hashHas(key) { var data = this.__data__; return nativeCreate ? data[key] !== void 0 : hasOwnProperty.call(data, key); } /** * Sets the hash `key` to `value`. * * @private * @name set * @memberOf Hash * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the hash instance. */ function hashSet(key, value) { var data = this.__data__; data[key] = nativeCreate && value === void 0 ? HASH_UNDEFINED : value; return this; } Hash.prototype.clear = hashClear; Hash.prototype["delete"] = hashDelete; Hash.prototype.get = hashGet; Hash.prototype.has = hashHas; Hash.prototype.set = hashSet; /** * Creates an list cache object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function ListCache(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the list cache. * * @private * @name clear * @memberOf ListCache */ function listCacheClear() { this.__data__ = []; } /** * Removes `key` and its value from the list cache. * * @private * @name delete * @memberOf ListCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function listCacheDelete(key) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) return false; if (index == data.length - 1) data.pop(); else splice.call(data, index, 1); return true; } /** * Gets the list cache value for `key`. * * @private * @name get * @memberOf ListCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function listCacheGet(key) { var data = this.__data__, index = assocIndexOf(data, key); return index < 0 ? void 0 : data[index][1]; } /** * Checks if a list cache value for `key` exists. * * @private * @name has * @memberOf ListCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function listCacheHas(key) { return assocIndexOf(this.__data__, key) > -1; } /** * Sets the list cache `key` to `value`. * * @private * @name set * @memberOf ListCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the list cache instance. */ function listCacheSet(key, value) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) data.push([key, value]); else data[index][1] = value; return this; } ListCache.prototype.clear = listCacheClear; ListCache.prototype["delete"] = listCacheDelete; ListCache.prototype.get = listCacheGet; ListCache.prototype.has = listCacheHas; ListCache.prototype.set = listCacheSet; /** * Creates a map cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function MapCache(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the map. * * @private * @name clear * @memberOf MapCache */ function mapCacheClear() { this.__data__ = { "hash": new Hash(), "map": new (Map$1 || ListCache)(), "string": new Hash() }; } /** * Removes `key` and its value from the map. * * @private * @name delete * @memberOf MapCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { return getMapData(this, key)["delete"](key); } /** * Gets the map value for `key`. * * @private * @name get * @memberOf MapCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function mapCacheGet(key) { return getMapData(this, key).get(key); } /** * Checks if a map value for `key` exists. * * @private * @name has * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapCacheHas(key) { return getMapData(this, key).has(key); } /** * Sets the map `key` to `value`. * * @private * @name set * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { getMapData(this, key).set(key, value); return this; } MapCache.prototype.clear = mapCacheClear; MapCache.prototype["delete"] = mapCacheDelete; MapCache.prototype.get = mapCacheGet; MapCache.prototype.has = mapCacheHas; MapCache.prototype.set = mapCacheSet; /** * Creates a stack cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { this.__data__ = new ListCache(entries); } /** * Removes all key-value entries from the stack. * * @private * @name clear * @memberOf Stack */ function stackClear() { this.__data__ = new ListCache(); } /** * Removes `key` and its value from the stack. * * @private * @name delete * @memberOf Stack * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { return this.__data__["delete"](key); } /** * Gets the stack value for `key`. * * @private * @name get * @memberOf Stack * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function stackGet(key) { return this.__data__.get(key); } /** * Checks if a stack value for `key` exists. * * @private * @name has * @memberOf Stack * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function stackHas(key) { return this.__data__.has(key); } /** * Sets the stack `key` to `value`. * * @private * @name set * @memberOf Stack * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { var cache = this.__data__; if (cache instanceof ListCache) { var pairs = cache.__data__; if (!Map$1 || pairs.length < LARGE_ARRAY_SIZE - 1) { pairs.push([key, value]); return this; } cache = this.__data__ = new MapCache(pairs); } cache.set(key, value); return this; } Stack.prototype.clear = stackClear; Stack.prototype["delete"] = stackDelete; Stack.prototype.get = stackGet; Stack.prototype.has = stackHas; Stack.prototype.set = stackSet; /** * Creates an array of the enumerable property names of the array-like `value`. * * @private * @param {*} value The value to query. * @param {boolean} inherited Specify returning inherited property names. * @returns {Array} Returns the array of property names. */ function arrayLikeKeys(value, inherited) { var result = isArray(value) || isArguments(value) ? baseTimes(value.length, String) : []; var length = result.length, skipIndexes = !!length; for (var key in value) if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == "length" || isIndex(key, length)))) result.push(key); return result; } /** * Assigns `value` to `key` of `object` if the existing value is not equivalent * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignValue(object, key, value) { var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === void 0 && !(key in object)) object[key] = value; } /** * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private * @param {Array} array The array to inspect. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ function assocIndexOf(array, key) { var length = array.length; while (length--) if (eq(array[length][0], key)) return length; return -1; } /** * The base implementation of `_.assign` without support for multiple sources * or `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssign(object, source) { return object && copyObject(source, keys(source), object); } /** * The base implementation of `_.clone` and `_.cloneDeep` which tracks * traversed objects. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {boolean} [isFull] Specify a clone including symbols. * @param {Function} [customizer] The function to customize cloning. * @param {string} [key] The key of `value`. * @param {Object} [object] The parent object of `value`. * @param {Object} [stack] Tracks traversed objects and their clone counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, isFull, customizer, key, object, stack) { var result; if (customizer) result = object ? customizer(value, key, object, stack) : customizer(value); if (result !== void 0) return result; if (!isObject(value)) return value; var isArr = isArray(value); if (isArr) { result = initCloneArray(value); if (!isDeep) return copyArray(value, result); } else { var tag = getTag(value), isFunc = tag == funcTag || tag == genTag; if (isBuffer(value)) return cloneBuffer(value, isDeep); if (tag == objectTag || tag == argsTag || isFunc && !object) { if (isHostObject(value)) return object ? value : {}; result = initCloneObject(isFunc ? {} : value); if (!isDeep) return copySymbols(value, baseAssign(result, value)); } else { if (!cloneableTags[tag]) return object ? value : {}; result = initCloneByTag(value, tag, baseClone, isDeep); } } stack || (stack = new Stack()); var stacked = stack.get(value); if (stacked) return stacked; stack.set(value, result); if (!isArr) var props = isFull ? getAllKeys(value) : keys(value); arrayEach(props || value, function(subValue, key$1) { if (props) { key$1 = subValue; subValue = value[key$1]; } assignValue(result, key$1, baseClone(subValue, isDeep, isFull, customizer, key$1, value, stack)); }); return result; } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} prototype The object to inherit from. * @returns {Object} Returns the new object. */ function baseCreate(proto) { return isObject(proto) ? objectCreate(proto) : {}; } /** * The base implementation of `getAllKeys` and `getAllKeysIn` which uses * `keysFunc` and `symbolsFunc` to get the enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @param {Function} keysFunc The function to get the keys of `object`. * @param {Function} symbolsFunc The function to get the symbols of `object`. * @returns {Array} Returns the array of property names and symbols. */ function baseGetAllKeys(object, keysFunc, symbolsFunc) { var result = keysFunc(object); return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); } /** * The base implementation of `getTag`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function baseGetTag(value) { return objectToString.call(value); } /** * The base implementation of `_.isNative` without bad shim checks. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, * else `false`. */ function baseIsNative(value) { if (!isObject(value) || isMasked(value)) return false; return (isFunction(value) || isHostObject(value) ? reIsNative : reIsHostCtor).test(toSource(value)); } /** * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { if (!isPrototype(object)) return nativeKeys(object); var result = []; for (var key in Object(object)) if (hasOwnProperty.call(object, key) && key != "constructor") result.push(key); return result; } /** * Creates a clone of `buffer`. * * @private * @param {Buffer} buffer The buffer to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Buffer} Returns the cloned buffer. */ function cloneBuffer(buffer, isDeep) { if (isDeep) return buffer.slice(); var result = new buffer.constructor(buffer.length); buffer.copy(result); return result; } /** * Creates a clone of `arrayBuffer`. * * @private * @param {ArrayBuffer} arrayBuffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function cloneArrayBuffer(arrayBuffer) { var result = new arrayBuffer.constructor(arrayBuffer.byteLength); new Uint8Array(result).set(new Uint8Array(arrayBuffer)); return result; } /** * Creates a clone of `dataView`. * * @private * @param {Object} dataView The data view to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned data view. */ function cloneDataView(dataView, isDeep) { var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); } /** * Creates a clone of `map`. * * @private * @param {Object} map The map to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned map. */ function cloneMap(map, isDeep, cloneFunc) { return arrayReduce(isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map), addMapEntry, new map.constructor()); } /** * Creates a clone of `regexp`. * * @private * @param {Object} regexp The regexp to clone. * @returns {Object} Returns the cloned regexp. */ function cloneRegExp(regexp) { var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); result.lastIndex = regexp.lastIndex; return result; } /** * Creates a clone of `set`. * * @private * @param {Object} set The set to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned set. */ function cloneSet(set, isDeep, cloneFunc) { return arrayReduce(isDeep ? cloneFunc(setToArray(set), true) : setToArray(set), addSetEntry, new set.constructor()); } /** * Creates a clone of the `symbol` object. * * @private * @param {Object} symbol The symbol object to clone. * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; } /** * Creates a clone of `typedArray`. * * @private * @param {Object} typedArray The typed array to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned typed array. */ function cloneTypedArray(typedArray, isDeep) { var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); } /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function copyArray(source, array) { var index = -1, length = source.length; array || (array = Array(length)); while (++index < length) array[index] = source[index]; return array; } /** * Copies properties of `source` to `object`. * * @private * @param {Object} source The object to copy properties from. * @param {Array} props The property identifiers to copy. * @param {Object} [object={}] The object to copy properties to. * @param {Function} [customizer] The function to customize copied values. * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { object || (object = {}); var index = -1, length = props.length; while (++index < length) { var key = props[index]; var newValue = customizer ? customizer(object[key], source[key], key, object, source) : void 0; assignValue(object, key, newValue === void 0 ? source[key] : newValue); } return object; } /** * Copies own symbol properties of `source` to `object`. * * @private * @param {Object} source The object to copy symbols from. * @param {Object} [object={}] The object to copy symbols to. * @returns {Object} Returns `object`. */ function copySymbols(source, object) { return copyObject(source, getSymbols(source), object); } /** * Creates an array of own enumerable property names and symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeys(object) { return baseGetAllKeys(object, keys, getSymbols); } /** * Gets the data for `map`. * * @private * @param {Object} map The map to query. * @param {string} key The reference key. * @returns {*} Returns the map data. */ function getMapData(map, key) { var data = map.__data__; return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = getValue(object, key); return baseIsNative(value) ? value : void 0; } /** * Creates an array of the own enumerable symbol properties of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray; /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ var getTag = baseGetTag; if (DataView && getTag(new DataView(/* @__PURE__ */ new ArrayBuffer(1))) != dataViewTag || Map$1 && getTag(new Map$1()) != mapTag || Promise$1 && getTag(Promise$1.resolve()) != promiseTag || Set$1 && getTag(new Set$1()) != setTag || WeakMap$1 && getTag(new WeakMap$1()) != weakMapTag) getTag = function(value) { var result = objectToString.call(value), Ctor = result == objectTag ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : void 0; if (ctorString) switch (ctorString) { case dataViewCtorString: return dataViewTag; case mapCtorString: return mapTag; case promiseCtorString: return promiseTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } return result; }; /** * Initializes an array clone. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the initialized clone. */ function initCloneArray(array) { var length = array.length, result = array.constructor(length); if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {Object} object The object to clone. * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {}; } /** * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to clone. * @param {string} tag The `toStringTag` of the object to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the initialized clone. */ function initCloneByTag(object, tag, cloneFunc, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: return cloneArrayBuffer(object); case boolTag: case dateTag: return new Ctor(+object); case dataViewTag: return cloneDataView(object, isDeep); case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: return cloneTypedArray(object, isDeep); case mapTag: return cloneMap(object, isDeep, cloneFunc); case numberTag: case stringTag: return new Ctor(object); case regexpTag: return cloneRegExp(object); case setTag: return cloneSet(object, isDeep, cloneFunc); case symbolTag: return cloneSymbol(object); } } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { length = length == null ? MAX_SAFE_INTEGER : length; return !!length && (typeof value == "number" || reIsUint.test(value)) && value > -1 && value % 1 == 0 && value < length; } /** * Checks if `value` is suitable for use as unique object key. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is suitable, else `false`. */ function isKeyable(value) { var type = typeof value; return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; } /** * Checks if `func` has its source masked. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` is masked, else `false`. */ function isMasked(func) { return !!maskSrcKey && maskSrcKey in func; } /** * Checks if `value` is likely a prototype object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ function isPrototype(value) { var Ctor = value && value.constructor; return value === (typeof Ctor == "function" && Ctor.prototype || objectProto); } /** * Converts `func` to its source code. * * @private * @param {Function} func The function to process. * @returns {string} Returns the source code. */ function toSource(func) { if (func != null) { try { return funcToString.call(func); } catch (e) {} try { return func + ""; } catch (e) {} } return ""; } /** * This method is like `_.clone` except that it recursively clones `value`. * * @static * @memberOf _ * @since 1.0.0 * @category Lang * @param {*} value The value to recursively clone. * @returns {*} Returns the deep cloned value. * @see _.clone * @example * * var objects = [{ 'a': 1 }, { 'b': 2 }]; * * var deep = _.cloneDeep(objects); * console.log(deep[0] === objects[0]); * // => false */ function cloneDeep$1(value) { return baseClone(value, true, true); } /** * Performs a * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'a': 1 }; * var other = { 'a': 1 }; * * _.eq(object, object); * // => true * * _.eq(object, other); * // => false * * _.eq('a', 'a'); * // => true * * _.eq('a', Object('a')); * // => false * * _.eq(NaN, NaN); * // => true */ function eq(value, other) { return value === other || value !== value && other !== other; } /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an `arguments` object, * else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { return isArrayLikeObject(value) && hasOwnProperty.call(value, "callee") && (!propertyIsEnumerable.call(value, "callee") || objectToString.call(value) == argsTag); } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(document.body.children); * // => false * * _.isArray('abc'); * // => false * * _.isArray(_.noop); * // => false */ var isArray = Array.isArray; /** * Checks if `value` is array-like. A value is considered array-like if it's * not a function and has a `value.length` that's an integer greater than or * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. * @example * * _.isArrayLike([1, 2, 3]); * // => true * * _.isArrayLike(document.body.children); * // => true * * _.isArrayLike('abc'); * // => true * * _.isArrayLike(_.noop); * // => false */ function isArrayLike(value) { return value != null && isLength(value.length) && !isFunction(value); } /** * This method is like `_.isArrayLike` except that it also checks if `value` * is an object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, * else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); * // => true * * _.isArrayLikeObject(document.body.children); * // => true * * _.isArrayLikeObject('abc'); * // => false * * _.isArrayLikeObject(_.noop); * // => false */ function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value); } /** * Checks if `value` is a buffer. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value