@cloudcome/utils-core 1.22.0 → 1.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/array.cjs.map +1 -1
- package/dist/array.mjs.map +1 -1
- package/dist/async.cjs +1 -0
- package/dist/async.cjs.map +1 -1
- package/dist/async.mjs +1 -0
- package/dist/async.mjs.map +1 -1
- package/dist/base64.cjs.map +1 -1
- package/dist/base64.mjs.map +1 -1
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.mjs.map +1 -1
- package/dist/color.cjs.map +1 -1
- package/dist/color.mjs.map +1 -1
- package/dist/crypto.cjs.map +1 -1
- package/dist/crypto.mjs.map +1 -1
- package/dist/date.cjs.map +1 -1
- package/dist/date.mjs.map +1 -1
- package/dist/dict.cjs.map +1 -1
- package/dist/dict.mjs.map +1 -1
- package/dist/easing.cjs.map +1 -1
- package/dist/easing.mjs.map +1 -1
- package/dist/emitter.cjs.map +1 -1
- package/dist/emitter.mjs.map +1 -1
- package/dist/env.cjs.map +1 -1
- package/dist/env.mjs.map +1 -1
- package/dist/error.cjs.map +1 -1
- package/dist/error.mjs.map +1 -1
- package/dist/function.cjs.map +1 -1
- package/dist/function.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/object.cjs.map +1 -1
- package/dist/object.mjs.map +1 -1
- package/dist/path.cjs.map +1 -1
- package/dist/path.mjs.map +1 -1
- package/dist/promise.cjs.map +1 -1
- package/dist/promise.mjs.map +1 -1
- package/dist/qs.cjs.map +1 -1
- package/dist/qs.mjs.map +1 -1
- package/dist/regexp.cjs.map +1 -1
- package/dist/regexp.mjs.map +1 -1
- package/dist/string2.cjs.map +1 -1
- package/dist/string2.mjs.map +1 -1
- package/dist/time.cjs.map +1 -1
- package/dist/time.mjs.map +1 -1
- package/dist/timer.cjs.map +1 -1
- package/dist/timer.mjs.map +1 -1
- package/dist/tree.cjs.map +1 -1
- package/dist/tree.mjs.map +1 -1
- package/dist/try.cjs.map +1 -1
- package/dist/try.mjs.map +1 -1
- package/dist/type.cjs.map +1 -1
- package/dist/type.mjs.map +1 -1
- package/dist/unique.cjs.map +1 -1
- package/dist/unique.mjs.map +1 -1
- package/dist/url.cjs.map +1 -1
- package/dist/url.mjs.map +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs.map +1 -1
- package/package.json +1 -9
- package/dist/exception.cjs +0 -40
- package/dist/exception.cjs.map +0 -1
- package/dist/exception.d.ts +0 -31
- package/dist/exception.mjs +0 -39
- package/dist/exception.mjs.map +0 -1
package/dist/easing.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"easing.cjs","names":[],"sources":["../src/easing.ts"],"sourcesContent":["/**\n * https://github.com/gre/bezier-easing\n * BezierEasing - use bezier curve for transition easing function\n * by Gaëtan Renaudeau 2014 - 2015 – MIT License\n */\n\n// These values are established by empiricism with tests (tradeoff: performance VS precision)\nconst NEWTON_ITERATIONS = 4;\nconst NEWTON_MIN_SLOPE = 0.001;\nconst SUBDIVISION_PRECISION = 0.0000001;\nconst SUBDIVISION_MAX_ITERATIONS = 10;\n\nconst kSplineTableSize = 11;\nconst kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\nconst float32ArraySupported = typeof Float32Array === 'function';\n\nfunction A(aA1: number, aA2: number) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n}\nfunction B(aA1: number, aA2: number) {\n return 3.0 * aA2 - 6.0 * aA1;\n}\nfunction C(aA1: number) {\n return 3.0 * aA1;\n}\n\n// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\nfunction calcBezier(aT: number, aA1: number, aA2: number) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n}\n\n// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\nfunction getSlope(aT: number, aA1: number, aA2: number) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n}\n\nfunction binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number) {\n let currentX: number;\n let currentT: number;\n let i = 0;\n let aBFinal = aB;\n let aAFinal = aA;\n\n do {\n currentT = aAFinal + (aBFinal - aAFinal) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) {\n aBFinal = currentT;\n } else {\n aAFinal = currentT;\n }\n } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n return currentT;\n}\n\nfunction newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) {\n let aGuessTFinal = aGuessT;\n for (let i = 0; i < NEWTON_ITERATIONS; ++i) {\n const currentSlope = getSlope(aGuessTFinal, mX1, mX2);\n if (currentSlope === 0.0) {\n return aGuessTFinal;\n }\n const currentX = calcBezier(aGuessTFinal, mX1, mX2) - aX;\n aGuessTFinal -= currentX / currentSlope;\n }\n return aGuessTFinal;\n}\n\nfunction LinearEasing(x: number) {\n return x;\n}\n\n/**\n * 创建一个基于贝塞尔曲线的缓动函数。\n *\n * @param x1 - 贝塞尔曲线的第一个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y1 - 贝塞尔曲线的第一个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @param x2 - 贝塞尔曲线的第二个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y2 - 贝塞尔曲线的第二个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @returns 返回一个缓动函数,该函数接受一个参数 x(范围在 0 到 1 之间),并返回相应的缓动值。\n * @throws 如果 mX1 或 mX2 不在 [0, 1] 范围内,则抛出错误。\n */\nexport function createEasingFn(x1: number, y1: number, x2: number, y2: number) {\n if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {\n throw new Error('bezier x values must be in [0, 1] range');\n }\n\n if (x1 === y1 && x2 === y2) {\n return LinearEasing;\n }\n\n // Precompute samples table\n const sampleValues = (\n float32ArraySupported ? new Float32Array(kSplineTableSize) : Array.from({ length: kSplineTableSize })\n ).map((v, i) => calcBezier(i * kSampleStepSize, x1, x2));\n\n function getTForX(aX: number) {\n let intervalStart = 0.0;\n let currentSample = 1;\n const lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n --currentSample;\n\n // Interpolate to provide an initial guess for t\n const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n const guessForT = intervalStart + dist * kSampleStepSize;\n const initialSlope = getSlope(guessForT, x1, x2);\n\n if (initialSlope >= NEWTON_MIN_SLOPE) {\n return newtonRaphsonIterate(aX, guessForT, x1, x2);\n }\n\n if (initialSlope === 0.0) {\n return guessForT;\n }\n\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, x1, x2);\n }\n\n /**\n * 贝塞尔曲线方程\n * @param x {number} 0~1\n */\n return function easingFunc(x: number) {\n // Because JavaScript number are imprecise, we should guarantee the extremes are right.\n if (x === 0 || x === 1) {\n return x;\n }\n\n return calcBezier(getTForX(x), y1, y2);\n };\n}\n\nexport const easingEase = createEasingFn(0.25, 0.1, 0.25, 1);\nexport const easingLinear = createEasingFn(0, 0, 1, 1);\nexport const easingSnap = createEasingFn(0, 1, 0.5, 1);\nexport const easingIn = createEasingFn(0.42, 0, 1, 1);\nexport const easingOut = createEasingFn(0, 0, 0.58, 1);\nexport const easingInOut = createEasingFn(0.42, 0, 0.58, 1);\nexport const easingInQuad = createEasingFn(0.55, 0.085, 0.68, 0.53);\nexport const easingInCubic = createEasingFn(0.55, 0.055, 0.675, 0.19);\nexport const easingInQuart = createEasingFn(0.895, 0.03, 0.685, 0.22);\nexport const easingInQuint = createEasingFn(0.755, 0.05, 0.855, 0.06);\nexport const easingInSine = createEasingFn(0.47, 0, 0.745, 0.715);\nexport const easingInExpo = createEasingFn(0.95, 0.05, 0.795, 0.035);\nexport const easingInCirc = createEasingFn(0.6, 0.04, 0.98, 0.335);\nexport const easingInBack = createEasingFn(0.6, -0.28, 0.735, 0.045);\nexport const easingOutQuad = createEasingFn(0.25, 0.46, 0.45, 0.94);\nexport const easingOutCubic = createEasingFn(0.215, 0.61, 0.355, 1);\nexport const easingOutQuart = createEasingFn(0.165, 0.84, 0.44, 1);\nexport const easingOutQuint = createEasingFn(0.23, 1, 0.32, 1);\nexport const easingOutSine = createEasingFn(0.39, 0.575, 0.565, 1);\nexport const easingOutExpo = createEasingFn(0.19, 1, 0.22, 1);\nexport const easingOutCirc = createEasingFn(0.075, 0.82, 0.165, 1);\nexport const easingOutBack = createEasingFn(0.175, 0.885, 0.32, 1.275);\nexport const easingInOutQuart = createEasingFn(0.77, 0, 0.175, 1);\nexport const easingInOutQuint = createEasingFn(0.86, 0, 0.07, 1);\nexport const easingInOutSine = createEasingFn(0.445, 0.05, 0.55, 0.95);\nexport const easingInOutExpo = createEasingFn(1, 0, 0, 1);\nexport const easingInOutCirc = createEasingFn(0.785, 0.135, 0.15, 0.86);\nexport const easingInOutBack = createEasingFn(0.68, -0.55, 0.265, 1.55);\n"],"mappings":";;;;;;;AAOA,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAEnC,IAAM,mBAAmB;AACzB,IAAM,kBAAkB,KAAO,mBAAmB;AAElD,IAAM,wBAAwB,OAAO,iBAAiB;AAEtD,SAAS,EAAE,KAAa,KAAa;CACnC,OAAO,IAAM,IAAM,MAAM,IAAM
|
|
1
|
+
{"version":3,"file":"easing.cjs","names":[],"sources":["../src/easing.ts"],"sourcesContent":["/**\n * https://github.com/gre/bezier-easing\n * BezierEasing - use bezier curve for transition easing function\n * by Gaëtan Renaudeau 2014 - 2015 – MIT License\n */\n\n// These values are established by empiricism with tests (tradeoff: performance VS precision)\nconst NEWTON_ITERATIONS = 4;\nconst NEWTON_MIN_SLOPE = 0.001;\nconst SUBDIVISION_PRECISION = 0.0000001;\nconst SUBDIVISION_MAX_ITERATIONS = 10;\n\nconst kSplineTableSize = 11;\nconst kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\nconst float32ArraySupported = typeof Float32Array === 'function';\n\nfunction A(aA1: number, aA2: number) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n}\nfunction B(aA1: number, aA2: number) {\n return 3.0 * aA2 - 6.0 * aA1;\n}\nfunction C(aA1: number) {\n return 3.0 * aA1;\n}\n\n// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\nfunction calcBezier(aT: number, aA1: number, aA2: number) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n}\n\n// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\nfunction getSlope(aT: number, aA1: number, aA2: number) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n}\n\nfunction binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number) {\n let currentX: number;\n let currentT: number;\n let i = 0;\n let aBFinal = aB;\n let aAFinal = aA;\n\n do {\n currentT = aAFinal + (aBFinal - aAFinal) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) {\n aBFinal = currentT;\n } else {\n aAFinal = currentT;\n }\n } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n return currentT;\n}\n\nfunction newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) {\n let aGuessTFinal = aGuessT;\n for (let i = 0; i < NEWTON_ITERATIONS; ++i) {\n const currentSlope = getSlope(aGuessTFinal, mX1, mX2);\n if (currentSlope === 0.0) {\n return aGuessTFinal;\n }\n const currentX = calcBezier(aGuessTFinal, mX1, mX2) - aX;\n aGuessTFinal -= currentX / currentSlope;\n }\n return aGuessTFinal;\n}\n\nfunction LinearEasing(x: number) {\n return x;\n}\n\n/**\n * 创建一个基于贝塞尔曲线的缓动函数。\n *\n * @param x1 - 贝塞尔曲线的第一个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y1 - 贝塞尔曲线的第一个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @param x2 - 贝塞尔曲线的第二个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y2 - 贝塞尔曲线的第二个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @returns 返回一个缓动函数,该函数接受一个参数 x(范围在 0 到 1 之间),并返回相应的缓动值。\n * @throws 如果 mX1 或 mX2 不在 [0, 1] 范围内,则抛出错误。\n */\nexport function createEasingFn(x1: number, y1: number, x2: number, y2: number) {\n if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {\n throw new Error('bezier x values must be in [0, 1] range');\n }\n\n if (x1 === y1 && x2 === y2) {\n return LinearEasing;\n }\n\n // Precompute samples table\n const sampleValues = (\n float32ArraySupported ? new Float32Array(kSplineTableSize) : Array.from({ length: kSplineTableSize })\n ).map((v, i) => calcBezier(i * kSampleStepSize, x1, x2));\n\n function getTForX(aX: number) {\n let intervalStart = 0.0;\n let currentSample = 1;\n const lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n --currentSample;\n\n // Interpolate to provide an initial guess for t\n const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n const guessForT = intervalStart + dist * kSampleStepSize;\n const initialSlope = getSlope(guessForT, x1, x2);\n\n if (initialSlope >= NEWTON_MIN_SLOPE) {\n return newtonRaphsonIterate(aX, guessForT, x1, x2);\n }\n\n if (initialSlope === 0.0) {\n return guessForT;\n }\n\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, x1, x2);\n }\n\n /**\n * 贝塞尔曲线方程\n * @param x {number} 0~1\n */\n return function easingFunc(x: number) {\n // Because JavaScript number are imprecise, we should guarantee the extremes are right.\n if (x === 0 || x === 1) {\n return x;\n }\n\n return calcBezier(getTForX(x), y1, y2);\n };\n}\n\nexport const easingEase = createEasingFn(0.25, 0.1, 0.25, 1);\nexport const easingLinear = createEasingFn(0, 0, 1, 1);\nexport const easingSnap = createEasingFn(0, 1, 0.5, 1);\nexport const easingIn = createEasingFn(0.42, 0, 1, 1);\nexport const easingOut = createEasingFn(0, 0, 0.58, 1);\nexport const easingInOut = createEasingFn(0.42, 0, 0.58, 1);\nexport const easingInQuad = createEasingFn(0.55, 0.085, 0.68, 0.53);\nexport const easingInCubic = createEasingFn(0.55, 0.055, 0.675, 0.19);\nexport const easingInQuart = createEasingFn(0.895, 0.03, 0.685, 0.22);\nexport const easingInQuint = createEasingFn(0.755, 0.05, 0.855, 0.06);\nexport const easingInSine = createEasingFn(0.47, 0, 0.745, 0.715);\nexport const easingInExpo = createEasingFn(0.95, 0.05, 0.795, 0.035);\nexport const easingInCirc = createEasingFn(0.6, 0.04, 0.98, 0.335);\nexport const easingInBack = createEasingFn(0.6, -0.28, 0.735, 0.045);\nexport const easingOutQuad = createEasingFn(0.25, 0.46, 0.45, 0.94);\nexport const easingOutCubic = createEasingFn(0.215, 0.61, 0.355, 1);\nexport const easingOutQuart = createEasingFn(0.165, 0.84, 0.44, 1);\nexport const easingOutQuint = createEasingFn(0.23, 1, 0.32, 1);\nexport const easingOutSine = createEasingFn(0.39, 0.575, 0.565, 1);\nexport const easingOutExpo = createEasingFn(0.19, 1, 0.22, 1);\nexport const easingOutCirc = createEasingFn(0.075, 0.82, 0.165, 1);\nexport const easingOutBack = createEasingFn(0.175, 0.885, 0.32, 1.275);\nexport const easingInOutQuart = createEasingFn(0.77, 0, 0.175, 1);\nexport const easingInOutQuint = createEasingFn(0.86, 0, 0.07, 1);\nexport const easingInOutSine = createEasingFn(0.445, 0.05, 0.55, 0.95);\nexport const easingInOutExpo = createEasingFn(1, 0, 0, 1);\nexport const easingInOutCirc = createEasingFn(0.785, 0.135, 0.15, 0.86);\nexport const easingInOutBack = createEasingFn(0.68, -0.55, 0.265, 1.55);\n"],"mappings":"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"}
|
package/dist/easing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"easing.mjs","names":[],"sources":["../src/easing.ts"],"sourcesContent":["/**\n * https://github.com/gre/bezier-easing\n * BezierEasing - use bezier curve for transition easing function\n * by Gaëtan Renaudeau 2014 - 2015 – MIT License\n */\n\n// These values are established by empiricism with tests (tradeoff: performance VS precision)\nconst NEWTON_ITERATIONS = 4;\nconst NEWTON_MIN_SLOPE = 0.001;\nconst SUBDIVISION_PRECISION = 0.0000001;\nconst SUBDIVISION_MAX_ITERATIONS = 10;\n\nconst kSplineTableSize = 11;\nconst kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\nconst float32ArraySupported = typeof Float32Array === 'function';\n\nfunction A(aA1: number, aA2: number) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n}\nfunction B(aA1: number, aA2: number) {\n return 3.0 * aA2 - 6.0 * aA1;\n}\nfunction C(aA1: number) {\n return 3.0 * aA1;\n}\n\n// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\nfunction calcBezier(aT: number, aA1: number, aA2: number) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n}\n\n// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\nfunction getSlope(aT: number, aA1: number, aA2: number) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n}\n\nfunction binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number) {\n let currentX: number;\n let currentT: number;\n let i = 0;\n let aBFinal = aB;\n let aAFinal = aA;\n\n do {\n currentT = aAFinal + (aBFinal - aAFinal) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) {\n aBFinal = currentT;\n } else {\n aAFinal = currentT;\n }\n } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n return currentT;\n}\n\nfunction newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) {\n let aGuessTFinal = aGuessT;\n for (let i = 0; i < NEWTON_ITERATIONS; ++i) {\n const currentSlope = getSlope(aGuessTFinal, mX1, mX2);\n if (currentSlope === 0.0) {\n return aGuessTFinal;\n }\n const currentX = calcBezier(aGuessTFinal, mX1, mX2) - aX;\n aGuessTFinal -= currentX / currentSlope;\n }\n return aGuessTFinal;\n}\n\nfunction LinearEasing(x: number) {\n return x;\n}\n\n/**\n * 创建一个基于贝塞尔曲线的缓动函数。\n *\n * @param x1 - 贝塞尔曲线的第一个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y1 - 贝塞尔曲线的第一个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @param x2 - 贝塞尔曲线的第二个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y2 - 贝塞尔曲线的第二个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @returns 返回一个缓动函数,该函数接受一个参数 x(范围在 0 到 1 之间),并返回相应的缓动值。\n * @throws 如果 mX1 或 mX2 不在 [0, 1] 范围内,则抛出错误。\n */\nexport function createEasingFn(x1: number, y1: number, x2: number, y2: number) {\n if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {\n throw new Error('bezier x values must be in [0, 1] range');\n }\n\n if (x1 === y1 && x2 === y2) {\n return LinearEasing;\n }\n\n // Precompute samples table\n const sampleValues = (\n float32ArraySupported ? new Float32Array(kSplineTableSize) : Array.from({ length: kSplineTableSize })\n ).map((v, i) => calcBezier(i * kSampleStepSize, x1, x2));\n\n function getTForX(aX: number) {\n let intervalStart = 0.0;\n let currentSample = 1;\n const lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n --currentSample;\n\n // Interpolate to provide an initial guess for t\n const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n const guessForT = intervalStart + dist * kSampleStepSize;\n const initialSlope = getSlope(guessForT, x1, x2);\n\n if (initialSlope >= NEWTON_MIN_SLOPE) {\n return newtonRaphsonIterate(aX, guessForT, x1, x2);\n }\n\n if (initialSlope === 0.0) {\n return guessForT;\n }\n\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, x1, x2);\n }\n\n /**\n * 贝塞尔曲线方程\n * @param x {number} 0~1\n */\n return function easingFunc(x: number) {\n // Because JavaScript number are imprecise, we should guarantee the extremes are right.\n if (x === 0 || x === 1) {\n return x;\n }\n\n return calcBezier(getTForX(x), y1, y2);\n };\n}\n\nexport const easingEase = createEasingFn(0.25, 0.1, 0.25, 1);\nexport const easingLinear = createEasingFn(0, 0, 1, 1);\nexport const easingSnap = createEasingFn(0, 1, 0.5, 1);\nexport const easingIn = createEasingFn(0.42, 0, 1, 1);\nexport const easingOut = createEasingFn(0, 0, 0.58, 1);\nexport const easingInOut = createEasingFn(0.42, 0, 0.58, 1);\nexport const easingInQuad = createEasingFn(0.55, 0.085, 0.68, 0.53);\nexport const easingInCubic = createEasingFn(0.55, 0.055, 0.675, 0.19);\nexport const easingInQuart = createEasingFn(0.895, 0.03, 0.685, 0.22);\nexport const easingInQuint = createEasingFn(0.755, 0.05, 0.855, 0.06);\nexport const easingInSine = createEasingFn(0.47, 0, 0.745, 0.715);\nexport const easingInExpo = createEasingFn(0.95, 0.05, 0.795, 0.035);\nexport const easingInCirc = createEasingFn(0.6, 0.04, 0.98, 0.335);\nexport const easingInBack = createEasingFn(0.6, -0.28, 0.735, 0.045);\nexport const easingOutQuad = createEasingFn(0.25, 0.46, 0.45, 0.94);\nexport const easingOutCubic = createEasingFn(0.215, 0.61, 0.355, 1);\nexport const easingOutQuart = createEasingFn(0.165, 0.84, 0.44, 1);\nexport const easingOutQuint = createEasingFn(0.23, 1, 0.32, 1);\nexport const easingOutSine = createEasingFn(0.39, 0.575, 0.565, 1);\nexport const easingOutExpo = createEasingFn(0.19, 1, 0.22, 1);\nexport const easingOutCirc = createEasingFn(0.075, 0.82, 0.165, 1);\nexport const easingOutBack = createEasingFn(0.175, 0.885, 0.32, 1.275);\nexport const easingInOutQuart = createEasingFn(0.77, 0, 0.175, 1);\nexport const easingInOutQuint = createEasingFn(0.86, 0, 0.07, 1);\nexport const easingInOutSine = createEasingFn(0.445, 0.05, 0.55, 0.95);\nexport const easingInOutExpo = createEasingFn(1, 0, 0, 1);\nexport const easingInOutCirc = createEasingFn(0.785, 0.135, 0.15, 0.86);\nexport const easingInOutBack = createEasingFn(0.68, -0.55, 0.265, 1.55);\n"],"mappings":";;;;;;AAOA,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAEnC,IAAM,mBAAmB;AACzB,IAAM,kBAAkB,KAAO,mBAAmB;AAElD,IAAM,wBAAwB,OAAO,iBAAiB;AAEtD,SAAS,EAAE,KAAa,KAAa;CACnC,OAAO,IAAM,IAAM,MAAM,IAAM
|
|
1
|
+
{"version":3,"file":"easing.mjs","names":[],"sources":["../src/easing.ts"],"sourcesContent":["/**\n * https://github.com/gre/bezier-easing\n * BezierEasing - use bezier curve for transition easing function\n * by Gaëtan Renaudeau 2014 - 2015 – MIT License\n */\n\n// These values are established by empiricism with tests (tradeoff: performance VS precision)\nconst NEWTON_ITERATIONS = 4;\nconst NEWTON_MIN_SLOPE = 0.001;\nconst SUBDIVISION_PRECISION = 0.0000001;\nconst SUBDIVISION_MAX_ITERATIONS = 10;\n\nconst kSplineTableSize = 11;\nconst kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\nconst float32ArraySupported = typeof Float32Array === 'function';\n\nfunction A(aA1: number, aA2: number) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n}\nfunction B(aA1: number, aA2: number) {\n return 3.0 * aA2 - 6.0 * aA1;\n}\nfunction C(aA1: number) {\n return 3.0 * aA1;\n}\n\n// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\nfunction calcBezier(aT: number, aA1: number, aA2: number) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n}\n\n// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\nfunction getSlope(aT: number, aA1: number, aA2: number) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n}\n\nfunction binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number) {\n let currentX: number;\n let currentT: number;\n let i = 0;\n let aBFinal = aB;\n let aAFinal = aA;\n\n do {\n currentT = aAFinal + (aBFinal - aAFinal) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) {\n aBFinal = currentT;\n } else {\n aAFinal = currentT;\n }\n } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n return currentT;\n}\n\nfunction newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) {\n let aGuessTFinal = aGuessT;\n for (let i = 0; i < NEWTON_ITERATIONS; ++i) {\n const currentSlope = getSlope(aGuessTFinal, mX1, mX2);\n if (currentSlope === 0.0) {\n return aGuessTFinal;\n }\n const currentX = calcBezier(aGuessTFinal, mX1, mX2) - aX;\n aGuessTFinal -= currentX / currentSlope;\n }\n return aGuessTFinal;\n}\n\nfunction LinearEasing(x: number) {\n return x;\n}\n\n/**\n * 创建一个基于贝塞尔曲线的缓动函数。\n *\n * @param x1 - 贝塞尔曲线的第一个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y1 - 贝塞尔曲线的第一个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @param x2 - 贝塞尔曲线的第二个控制点的 X 坐标,必须在 [0, 1] 范围内。\n * @param y2 - 贝塞尔曲线的第二个控制点的 Y 坐标,必须在 [0, 1] 范围内。\n * @returns 返回一个缓动函数,该函数接受一个参数 x(范围在 0 到 1 之间),并返回相应的缓动值。\n * @throws 如果 mX1 或 mX2 不在 [0, 1] 范围内,则抛出错误。\n */\nexport function createEasingFn(x1: number, y1: number, x2: number, y2: number) {\n if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {\n throw new Error('bezier x values must be in [0, 1] range');\n }\n\n if (x1 === y1 && x2 === y2) {\n return LinearEasing;\n }\n\n // Precompute samples table\n const sampleValues = (\n float32ArraySupported ? new Float32Array(kSplineTableSize) : Array.from({ length: kSplineTableSize })\n ).map((v, i) => calcBezier(i * kSampleStepSize, x1, x2));\n\n function getTForX(aX: number) {\n let intervalStart = 0.0;\n let currentSample = 1;\n const lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n --currentSample;\n\n // Interpolate to provide an initial guess for t\n const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n const guessForT = intervalStart + dist * kSampleStepSize;\n const initialSlope = getSlope(guessForT, x1, x2);\n\n if (initialSlope >= NEWTON_MIN_SLOPE) {\n return newtonRaphsonIterate(aX, guessForT, x1, x2);\n }\n\n if (initialSlope === 0.0) {\n return guessForT;\n }\n\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, x1, x2);\n }\n\n /**\n * 贝塞尔曲线方程\n * @param x {number} 0~1\n */\n return function easingFunc(x: number) {\n // Because JavaScript number are imprecise, we should guarantee the extremes are right.\n if (x === 0 || x === 1) {\n return x;\n }\n\n return calcBezier(getTForX(x), y1, y2);\n };\n}\n\nexport const easingEase = createEasingFn(0.25, 0.1, 0.25, 1);\nexport const easingLinear = createEasingFn(0, 0, 1, 1);\nexport const easingSnap = createEasingFn(0, 1, 0.5, 1);\nexport const easingIn = createEasingFn(0.42, 0, 1, 1);\nexport const easingOut = createEasingFn(0, 0, 0.58, 1);\nexport const easingInOut = createEasingFn(0.42, 0, 0.58, 1);\nexport const easingInQuad = createEasingFn(0.55, 0.085, 0.68, 0.53);\nexport const easingInCubic = createEasingFn(0.55, 0.055, 0.675, 0.19);\nexport const easingInQuart = createEasingFn(0.895, 0.03, 0.685, 0.22);\nexport const easingInQuint = createEasingFn(0.755, 0.05, 0.855, 0.06);\nexport const easingInSine = createEasingFn(0.47, 0, 0.745, 0.715);\nexport const easingInExpo = createEasingFn(0.95, 0.05, 0.795, 0.035);\nexport const easingInCirc = createEasingFn(0.6, 0.04, 0.98, 0.335);\nexport const easingInBack = createEasingFn(0.6, -0.28, 0.735, 0.045);\nexport const easingOutQuad = createEasingFn(0.25, 0.46, 0.45, 0.94);\nexport const easingOutCubic = createEasingFn(0.215, 0.61, 0.355, 1);\nexport const easingOutQuart = createEasingFn(0.165, 0.84, 0.44, 1);\nexport const easingOutQuint = createEasingFn(0.23, 1, 0.32, 1);\nexport const easingOutSine = createEasingFn(0.39, 0.575, 0.565, 1);\nexport const easingOutExpo = createEasingFn(0.19, 1, 0.22, 1);\nexport const easingOutCirc = createEasingFn(0.075, 0.82, 0.165, 1);\nexport const easingOutBack = createEasingFn(0.175, 0.885, 0.32, 1.275);\nexport const easingInOutQuart = createEasingFn(0.77, 0, 0.175, 1);\nexport const easingInOutQuint = createEasingFn(0.86, 0, 0.07, 1);\nexport const easingInOutSine = createEasingFn(0.445, 0.05, 0.55, 0.95);\nexport const easingInOutExpo = createEasingFn(1, 0, 0, 1);\nexport const easingInOutCirc = createEasingFn(0.785, 0.135, 0.15, 0.86);\nexport const easingInOutBack = createEasingFn(0.68, -0.55, 0.265, 1.55);\n"],"mappings":"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"}
|
package/dist/emitter.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitter.cjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (...payloads: E[K]) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<E extends EmitterMap = Record<string | symbol, unknown[]>> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(event: K, ...payloads: Parameters<EmitterListener<E, K>>) {\n const listeners = this.#events.get(event) as Set<EmitterListener<E, K>> | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n // oxlint-disable-next-line unicorn/no-useless-spread\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8BA,IAAa,UAAb,MAAgF;CAC9E,0BAA0C,IAAI,
|
|
1
|
+
{"version":3,"file":"emitter.cjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (...payloads: E[K]) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<E extends EmitterMap = Record<string | symbol, unknown[]>> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(event: K, ...payloads: Parameters<EmitterListener<E, K>>) {\n const listeners = this.#events.get(event) as Set<EmitterListener<E, K>> | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n // oxlint-disable-next-line unicorn/no-useless-spread\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8BA,IAAa,UAAb,MAAgF;CAC9E,0BAA0C,IAAI,IAAI;;;;;;;;;;CAWlD,GAAsB,OAAU,UAAiC;EAC/D,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EACxC,IAAI,WACF,UAAU,IAAI,QAAQ;OAEtB,KAAKA,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;CAE/C;;;;;;;;;;CAWA,KAAwB,OAAU,UAAiC;EACjE,MAAM,gBAAgB,GAAG,aAAgD;GACvE,MAAM,SAAS,SAAS,GAAG,QAAQ;GACnC,KAAK,IAAI,OAAO,YAAY;GAC5B,OAAO;EACT;EACA,KAAK,GAAG,OAAO,YAAY;CAC7B;;;;;;;;;;;;;;;;;;CAmBA,IAAuB,OAAW,UAAkC;EAClE,IAAI,SAAS,UACX,KAAKC,aAAa,OAAO,QAAQ;OAC5B,IAAI,OACT,KAAKC,UAAU,KAAK;OAEpB,KAAKC,QAAQ;CAEjB;CAEA,UAAU;EACR,KAAKH,QAAQ,MAAM;CACrB;CAEA,UAA6B,OAAU;EACrC,KAAKA,QAAQ,OAAO,KAAK;CAC3B;CAEA,aAAgC,OAAU,UAAiC;EACzE,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EAExC,IAAI,WACF,UAAU,OAAO,QAAQ;CAE7B;;;;;;;;;;;CAYA,KAAwB,OAAU,GAAG,UAA6C;EAChF,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EAExC,IAAI,CAAC,WAAW;EAIhB,KAAK,MAAM,YAAY,CAAC,GAAG,SAAS,GAClC,IAAI,SAAS,GAAG,QAAQ,MAAM,OAC5B;CAGN;AACF"}
|
package/dist/emitter.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitter.mjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (...payloads: E[K]) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<E extends EmitterMap = Record<string | symbol, unknown[]>> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(event: K, ...payloads: Parameters<EmitterListener<E, K>>) {\n const listeners = this.#events.get(event) as Set<EmitterListener<E, K>> | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n // oxlint-disable-next-line unicorn/no-useless-spread\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA8BA,IAAa,UAAb,MAAgF;CAC9E,0BAA0C,IAAI,
|
|
1
|
+
{"version":3,"file":"emitter.mjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (...payloads: E[K]) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<E extends EmitterMap = Record<string | symbol, unknown[]>> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(event: K, ...payloads: Parameters<EmitterListener<E, K>>) {\n const listeners = this.#events.get(event) as Set<EmitterListener<E, K>> | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n // oxlint-disable-next-line unicorn/no-useless-spread\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA8BA,IAAa,UAAb,MAAgF;CAC9E,0BAA0C,IAAI,IAAI;;;;;;;;;;CAWlD,GAAsB,OAAU,UAAiC;EAC/D,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EACxC,IAAI,WACF,UAAU,IAAI,QAAQ;OAEtB,KAAKA,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;CAE/C;;;;;;;;;;CAWA,KAAwB,OAAU,UAAiC;EACjE,MAAM,gBAAgB,GAAG,aAAgD;GACvE,MAAM,SAAS,SAAS,GAAG,QAAQ;GACnC,KAAK,IAAI,OAAO,YAAY;GAC5B,OAAO;EACT;EACA,KAAK,GAAG,OAAO,YAAY;CAC7B;;;;;;;;;;;;;;;;;;CAmBA,IAAuB,OAAW,UAAkC;EAClE,IAAI,SAAS,UACX,KAAKC,aAAa,OAAO,QAAQ;OAC5B,IAAI,OACT,KAAKC,UAAU,KAAK;OAEpB,KAAKC,QAAQ;CAEjB;CAEA,UAAU;EACR,KAAKH,QAAQ,MAAM;CACrB;CAEA,UAA6B,OAAU;EACrC,KAAKA,QAAQ,OAAO,KAAK;CAC3B;CAEA,aAAgC,OAAU,UAAiC;EACzE,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EAExC,IAAI,WACF,UAAU,OAAO,QAAQ;CAE7B;;;;;;;;;;;CAYA,KAAwB,OAAU,GAAG,UAA6C;EAChF,MAAM,YAAY,KAAKA,QAAQ,IAAI,KAAK;EAExC,IAAI,CAAC,WAAW;EAIhB,KAAK,MAAM,YAAY,CAAC,GAAG,SAAS,GAClC,IAAI,SAAS,GAAG,QAAQ,MAAM,OAC5B;CAGN;AACF"}
|
package/dist/env.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.cjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return typeof process !== 'undefined' && !isNullish(process.versions) && !isNullish(process.versions.node);\n}\n\n/**\n * 判断当前环境是否为 Web Worker 环境\n * @returns 如果是 Web Worker 环境返回 true,否则返回 false\n * @remarks\n * 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义\n */\nexport function isWorker() {\n // @ts-expect-error\n return typeof self !== 'undefined' && self.importScripts != null;\n}\n\n/**\n * 判断当前操作系统是否为 macOS\n * @returns 如果是 macOS 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isMacOS() {\n return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Linux\n * @returns 如果是 Linux 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isLinux() {\n return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Windows\n * @returns 如果是 Windows 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isWindows() {\n return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,YAAY;CAG1B,OAAO,OAAO,WAAW,eAAe,OAAO,aAAa
|
|
1
|
+
{"version":3,"file":"env.cjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return typeof process !== 'undefined' && !isNullish(process.versions) && !isNullish(process.versions.node);\n}\n\n/**\n * 判断当前环境是否为 Web Worker 环境\n * @returns 如果是 Web Worker 环境返回 true,否则返回 false\n * @remarks\n * 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义\n */\nexport function isWorker() {\n // @ts-expect-error\n return typeof self !== 'undefined' && self.importScripts != null;\n}\n\n/**\n * 判断当前操作系统是否为 macOS\n * @returns 如果是 macOS 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isMacOS() {\n return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Linux\n * @returns 如果是 Linux 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isLinux() {\n return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Windows\n * @returns 如果是 Windows 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isWindows() {\n return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,YAAY;CAG1B,OAAO,OAAO,WAAW,eAAe,OAAO,aAAa;AAC9D;;;;;AAMA,SAAgB,SAAS;CAGvB,OAAO,OAAO,YAAY,eAAe,CAAC,aAAA,UAAU,QAAQ,QAAQ,KAAK,CAAC,aAAA,UAAU,QAAQ,SAAS,IAAI;AAC3G;;;;;;;AAQA,SAAgB,WAAW;CAEzB,OAAO,OAAO,SAAS,eAAe,KAAK,iBAAiB;AAC9D;;;;;;;AAQA,SAAgB,UAAU;CACxB,OAAO,UAAU,IAAI,QAAQ,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,WAAW,KAAK,QAAQ,QAAQ,IAAI;AACzG;;;;;;;AAQA,SAAgB,UAAU;CACxB,OAAO,UAAU,IAAI,UAAU,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,UAAU,KAAK,QAAQ,QAAQ,IAAI;AAC1G;;;;;;;AAQA,SAAgB,YAAY;CAC1B,OAAO,UAAU,IAAI,QAAQ,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,QAAQ,KAAK,QAAQ,QAAQ,IAAI;AACtG"}
|
package/dist/env.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.mjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return typeof process !== 'undefined' && !isNullish(process.versions) && !isNullish(process.versions.node);\n}\n\n/**\n * 判断当前环境是否为 Web Worker 环境\n * @returns 如果是 Web Worker 环境返回 true,否则返回 false\n * @remarks\n * 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义\n */\nexport function isWorker() {\n // @ts-expect-error\n return typeof self !== 'undefined' && self.importScripts != null;\n}\n\n/**\n * 判断当前操作系统是否为 macOS\n * @returns 如果是 macOS 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isMacOS() {\n return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Linux\n * @returns 如果是 Linux 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isLinux() {\n return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Windows\n * @returns 如果是 Windows 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isWindows() {\n return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;\n}\n"],"mappings":";;;;;;AAMA,SAAgB,YAAY;CAG1B,OAAO,OAAO,WAAW,eAAe,OAAO,aAAa
|
|
1
|
+
{"version":3,"file":"env.mjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return typeof process !== 'undefined' && !isNullish(process.versions) && !isNullish(process.versions.node);\n}\n\n/**\n * 判断当前环境是否为 Web Worker 环境\n * @returns 如果是 Web Worker 环境返回 true,否则返回 false\n * @remarks\n * 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义\n */\nexport function isWorker() {\n // @ts-expect-error\n return typeof self !== 'undefined' && self.importScripts != null;\n}\n\n/**\n * 判断当前操作系统是否为 macOS\n * @returns 如果是 macOS 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isMacOS() {\n return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Linux\n * @returns 如果是 Linux 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isLinux() {\n return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;\n}\n\n/**\n * 判断当前操作系统是否为 Windows\n * @returns 如果是 Windows 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isWindows() {\n return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;\n}\n"],"mappings":";;;;;;AAMA,SAAgB,YAAY;CAG1B,OAAO,OAAO,WAAW,eAAe,OAAO,aAAa;AAC9D;;;;;AAMA,SAAgB,SAAS;CAGvB,OAAO,OAAO,YAAY,eAAe,CAAC,UAAU,QAAQ,QAAQ,KAAK,CAAC,UAAU,QAAQ,SAAS,IAAI;AAC3G;;;;;;;AAQA,SAAgB,WAAW;CAEzB,OAAO,OAAO,SAAS,eAAe,KAAK,iBAAiB;AAC9D;;;;;;;AAQA,SAAgB,UAAU;CACxB,OAAO,UAAU,IAAI,QAAQ,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,WAAW,KAAK,QAAQ,QAAQ,IAAI;AACzG;;;;;;;AAQA,SAAgB,UAAU;CACxB,OAAO,UAAU,IAAI,UAAU,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,UAAU,KAAK,QAAQ,QAAQ,IAAI;AAC1G;;;;;;;AAQA,SAAgB,YAAY;CAC1B,OAAO,UAAU,IAAI,QAAQ,KAAK,UAAU,QAAQ,IAAI,OAAO,IAAI,QAAQ,KAAK,QAAQ,QAAQ,IAAI;AACtG"}
|
package/dist/error.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.cjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { isError, isNullish } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 标准化处理 Error 对象,适用于 try-catch\n * @param throwError 接收抛出的错误字符串或者 Error 对象或字符串\n * @returns {Error}\n * @example\n * const error = errorNormalize('这是一个错误');\n * console.log(error.message); // 输出: 这是一个错误\n */\nexport function errorNormalize<E extends Error | unknown = unknown>(throwError: E) {\n return (\n isError(throwError) ? throwError : new Error(String(isNullish(throwError) ? '' : throwError))\n ) as E extends Error ? E : Error;\n}\n\n/**\n * 分配对象到 Error 对象上,适用于扩展 Error 实例,不影响原型和构造函数\n * @param {Error} error\n * @param {E} source\n * @returns {Error & E}\n * @example\n * const error = new Error('原始错误');\n * const extendedError = errorAssign(error, { code: 404, message: '未找到资源' });\n * console.log(extendedError.code); // 输出: 404\n * console.log(extendedError.message); // 输出: 未找到资源\n */\nexport function errorAssign<E extends AnyObject>(error: Error, source: E): Error & E {\n return Object.assign(error, source) as Error & E;\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,eAAoD,YAAe;CACjF,OACE,aAAA,QAAQ,
|
|
1
|
+
{"version":3,"file":"error.cjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { isError, isNullish } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 标准化处理 Error 对象,适用于 try-catch\n * @param throwError 接收抛出的错误字符串或者 Error 对象或字符串\n * @returns {Error}\n * @example\n * const error = errorNormalize('这是一个错误');\n * console.log(error.message); // 输出: 这是一个错误\n */\nexport function errorNormalize<E extends Error | unknown = unknown>(throwError: E) {\n return (\n isError(throwError) ? throwError : new Error(String(isNullish(throwError) ? '' : throwError))\n ) as E extends Error ? E : Error;\n}\n\n/**\n * 分配对象到 Error 对象上,适用于扩展 Error 实例,不影响原型和构造函数\n * @param {Error} error\n * @param {E} source\n * @returns {Error & E}\n * @example\n * const error = new Error('原始错误');\n * const extendedError = errorAssign(error, { code: 404, message: '未找到资源' });\n * console.log(extendedError.code); // 输出: 404\n * console.log(extendedError.message); // 输出: 未找到资源\n */\nexport function errorAssign<E extends AnyObject>(error: Error, source: E): Error & E {\n return Object.assign(error, source) as Error & E;\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,eAAoD,YAAe;CACjF,OACE,aAAA,QAAQ,UAAU,IAAI,aAAa,IAAI,MAAM,OAAO,aAAA,UAAU,UAAU,IAAI,KAAK,UAAU,CAAC;AAEhG;;;;;;;;;;;;AAaA,SAAgB,YAAiC,OAAc,QAAsB;CACnF,OAAO,OAAO,OAAO,OAAO,MAAM;AACpC"}
|
package/dist/error.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.mjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { isError, isNullish } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 标准化处理 Error 对象,适用于 try-catch\n * @param throwError 接收抛出的错误字符串或者 Error 对象或字符串\n * @returns {Error}\n * @example\n * const error = errorNormalize('这是一个错误');\n * console.log(error.message); // 输出: 这是一个错误\n */\nexport function errorNormalize<E extends Error | unknown = unknown>(throwError: E) {\n return (\n isError(throwError) ? throwError : new Error(String(isNullish(throwError) ? '' : throwError))\n ) as E extends Error ? E : Error;\n}\n\n/**\n * 分配对象到 Error 对象上,适用于扩展 Error 实例,不影响原型和构造函数\n * @param {Error} error\n * @param {E} source\n * @returns {Error & E}\n * @example\n * const error = new Error('原始错误');\n * const extendedError = errorAssign(error, { code: 404, message: '未找到资源' });\n * console.log(extendedError.code); // 输出: 404\n * console.log(extendedError.message); // 输出: 未找到资源\n */\nexport function errorAssign<E extends AnyObject>(error: Error, source: E): Error & E {\n return Object.assign(error, source) as Error & E;\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,eAAoD,YAAe;CACjF,OACE,QAAQ,
|
|
1
|
+
{"version":3,"file":"error.mjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import { isError, isNullish } from './type';\nimport type { AnyObject } from './types';\n\n/**\n * 标准化处理 Error 对象,适用于 try-catch\n * @param throwError 接收抛出的错误字符串或者 Error 对象或字符串\n * @returns {Error}\n * @example\n * const error = errorNormalize('这是一个错误');\n * console.log(error.message); // 输出: 这是一个错误\n */\nexport function errorNormalize<E extends Error | unknown = unknown>(throwError: E) {\n return (\n isError(throwError) ? throwError : new Error(String(isNullish(throwError) ? '' : throwError))\n ) as E extends Error ? E : Error;\n}\n\n/**\n * 分配对象到 Error 对象上,适用于扩展 Error 实例,不影响原型和构造函数\n * @param {Error} error\n * @param {E} source\n * @returns {Error & E}\n * @example\n * const error = new Error('原始错误');\n * const extendedError = errorAssign(error, { code: 404, message: '未找到资源' });\n * console.log(extendedError.code); // 输出: 404\n * console.log(extendedError.message); // 输出: 未找到资源\n */\nexport function errorAssign<E extends AnyObject>(error: Error, source: E): Error & E {\n return Object.assign(error, source) as Error & E;\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,eAAoD,YAAe;CACjF,OACE,QAAQ,UAAU,IAAI,aAAa,IAAI,MAAM,OAAO,UAAU,UAAU,IAAI,KAAK,UAAU,CAAC;AAEhG;;;;;;;;;;;;AAaA,SAAgB,YAAiC,OAAc,QAAsB;CACnF,OAAO,OAAO,OAAO,OAAO,MAAM;AACpC"}
|
package/dist/function.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.cjs","names":[],"sources":["../src/function.ts"],"sourcesContent":["import { promiseDelay } from './promise';\nimport { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n\nexport type FnRetryOptions = {\n /**\n * 最大尝试次数\n */\n maxAttempts?: number;\n /**\n * 每次重试之间的延迟时间(毫秒)\n * @default 0\n */\n delay?: number;\n /**\n * 自定义重试条件,返回 true 时触发重试\n * @default 仅在抛出错误时重试\n */\n retryWhen?: (error: unknown) => boolean;\n};\n\n/**\n * 创建一个带重试能力的函数,失败时自动重试直到成功或耗尽次数。\n *\n * @param fn - 需要重试的函数。\n * @param options - 重试配置选项。\n * @returns 返回一个带重试能力的函数。\n *\n * @example\n * ```typescript\n * const fetchData = fnRetry(async () => {\n * return await api.request('/data');\n * }, { maxAttempts: 3, delay: 1000 });\n *\n * // 第1次失败 → 等待1s → 第2次失败 → 等待1s → 第3次成功 → 返回结果\n * const result = await fetchData();\n * ```\n */\nexport function fnRetry<F extends AnyFunction>(fn: F, options: FnRetryOptions = {}) {\n const { maxAttempts = 3, delay = 0, retryWhen } = options;\n\n return async function (this: unknown, ...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return (await fn.apply(this, args)) as Awaited<ReturnType<F>>;\n } catch (error) {\n lastError = error;\n\n if (retryWhen && !retryWhen(error)) break;\n\n if (attempt < maxAttempts && delay > 0) {\n await promiseDelay(delay);\n }\n }\n }\n\n throw lastError;\n };\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,SAAS;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"function.cjs","names":[],"sources":["../src/function.ts"],"sourcesContent":["import { promiseDelay } from './promise';\nimport { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n\nexport type FnRetryOptions = {\n /**\n * 最大尝试次数\n */\n maxAttempts?: number;\n /**\n * 每次重试之间的延迟时间(毫秒)\n * @default 0\n */\n delay?: number;\n /**\n * 自定义重试条件,返回 true 时触发重试\n * @default 仅在抛出错误时重试\n */\n retryWhen?: (error: unknown) => boolean;\n};\n\n/**\n * 创建一个带重试能力的函数,失败时自动重试直到成功或耗尽次数。\n *\n * @param fn - 需要重试的函数。\n * @param options - 重试配置选项。\n * @returns 返回一个带重试能力的函数。\n *\n * @example\n * ```typescript\n * const fetchData = fnRetry(async () => {\n * return await api.request('/data');\n * }, { maxAttempts: 3, delay: 1000 });\n *\n * // 第1次失败 → 等待1s → 第2次失败 → 等待1s → 第3次成功 → 返回结果\n * const result = await fetchData();\n * ```\n */\nexport function fnRetry<F extends AnyFunction>(fn: F, options: FnRetryOptions = {}) {\n const { maxAttempts = 3, delay = 0, retryWhen } = options;\n\n return async function (this: unknown, ...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return (await fn.apply(this, args)) as Awaited<ReturnType<F>>;\n } catch (error) {\n lastError = error;\n\n if (retryWhen && !retryWhen(error)) break;\n\n if (attempt < maxAttempts && delay > 0) {\n await promiseDelay(delay);\n }\n }\n }\n\n throw lastError;\n };\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,SAAS,CAEzB;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,WAAkC,IAAO,MAAgC;CACvF,MAAM,UAA2B,aAAA,SAAS,IAAI,IAAI,EAAE,KAAK,IAAI;CAC7D,IAAI,WAAW;CAEf,IAAI;CACJ,IAAI,UAAU;CAEd,MAAM,YAAY,SAAyB,GAAG,MAAqB;EACjE,IAAI,UAAU;EAGd,IAAI,QAAQ,WAAW,CAAC,SAAS;GAC/B,UAAU;GACV,GAAG,MAAM,MAAM,IAAI;GACnB;EACF;EAGA,aAAa,KAAK;EAClB,QAAQ,iBAAiB;GACvB,IAAI,UAAU;GAEd,GAAG,MAAM,MAAM,IAAI;EACrB,GAAG,QAAQ,IAAI;CACjB;CAEA,UAAU,eAAe;EACvB,aAAa,KAAK;EAClB,WAAW;CACb;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,WAAkC,IAAO,MAAgC;CACvF,MAAM,UAAU,aAAA,SAAS,IAAI,IAAI,EAAE,KAAK,IAAI;CAC5C,MAAM,YAAY,QAAQ;CAC1B,IAAI,WAAW;CACf,IAAI,WAAW;CAEf,IAAI;CAEJ,MAAM,YAAY,SAAyB,GAAG,MAAqB;EACjE,IAAI,UAAU;EAEd,MAAM,MAAM,KAAK,IAAI;EACrB,IAAI,WAAW;EAGf,IAAI,QAAQ,WAAW,aAAa,GAAG;GACrC,WAAW;GACX,GAAG,MAAM,MAAM,IAAI;GACnB,WAAW;EACb,OAGK,IAAI,WAAW,KAAK,MAAM,YAAY,WAAW;GACpD,WAAW;GACX,GAAG,MAAM,MAAM,IAAI;GACnB,WAAW;EACb,OAGK,IAAI,aAAa,GACpB,WAAW;EAIb,IAAI,QAAQ,YAAY,CAAC,UAAU;GACjC,aAAa,KAAK;GAClB,QAAQ,iBAAiB;IACvB,GAAG,MAAM,MAAM,IAAI;GACrB,GAAG,SAAS;EACd;CACF;CAEA,UAAU,eAAe;EACvB,WAAW;EACX,aAAa,KAAK;CACpB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,OAA8B,IAAO;CACnD,IAAI,SAAS;CAEb,IAAI;CAEJ,OAAO,SAAyB,GAAG,MAAqB;EACtD,IAAI,CAAC,QAAQ;GACX,SAAS;GACT,SAAS,GAAG,MAAM,MAAM,IAAI;EAC9B;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,QAA+B,IAAO,UAA0B,CAAC,GAAG;CAClF,MAAM,EAAE,cAAc,GAAG,QAAQ,GAAG,cAAc;CAElD,OAAO,eAA+B,GAAG,MAAsD;EAC7F,IAAI;EAEJ,KAAK,IAAI,UAAU,GAAG,WAAW,aAAa,WAC5C,IAAI;GACF,OAAQ,MAAM,GAAG,MAAM,MAAM,IAAI;EACnC,SAAS,OAAO;GACd,YAAY;GAEZ,IAAI,aAAa,CAAC,UAAU,KAAK,GAAG;GAEpC,IAAI,UAAU,eAAe,QAAQ,GACnC,MAAM,gBAAA,aAAa,KAAK;EAE5B;EAGF,MAAM;CACR;AACF"}
|
package/dist/function.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"function.mjs","names":[],"sources":["../src/function.ts"],"sourcesContent":["import { promiseDelay } from './promise';\nimport { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n\nexport type FnRetryOptions = {\n /**\n * 最大尝试次数\n */\n maxAttempts?: number;\n /**\n * 每次重试之间的延迟时间(毫秒)\n * @default 0\n */\n delay?: number;\n /**\n * 自定义重试条件,返回 true 时触发重试\n * @default 仅在抛出错误时重试\n */\n retryWhen?: (error: unknown) => boolean;\n};\n\n/**\n * 创建一个带重试能力的函数,失败时自动重试直到成功或耗尽次数。\n *\n * @param fn - 需要重试的函数。\n * @param options - 重试配置选项。\n * @returns 返回一个带重试能力的函数。\n *\n * @example\n * ```typescript\n * const fetchData = fnRetry(async () => {\n * return await api.request('/data');\n * }, { maxAttempts: 3, delay: 1000 });\n *\n * // 第1次失败 → 等待1s → 第2次失败 → 等待1s → 第3次成功 → 返回结果\n * const result = await fetchData();\n * ```\n */\nexport function fnRetry<F extends AnyFunction>(fn: F, options: FnRetryOptions = {}) {\n const { maxAttempts = 3, delay = 0, retryWhen } = options;\n\n return async function (this: unknown, ...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return (await fn.apply(this, args)) as Awaited<ReturnType<F>>;\n } catch (error) {\n lastError = error;\n\n if (retryWhen && !retryWhen(error)) break;\n\n if (attempt < maxAttempts && delay > 0) {\n await promiseDelay(delay);\n }\n }\n }\n\n throw lastError;\n };\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,SAAS;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"function.mjs","names":[],"sources":["../src/function.ts"],"sourcesContent":["import { promiseDelay } from './promise';\nimport { isNumber } from './type';\nimport type { AnyFunction } from './types';\n\n/**\n * 一个空操作函数,不执行任何操作。\n *\n * @example\n * ```typescript\n * fnNoop(); // 不执行任何操作\n * ```\n */\nexport function fnNoop() {\n //\n}\n\n/**\n * 防抖函数的配置选项。\n */\nexport type DebounceOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n /**\n * 是否在等待开始时立即执行一次\n * @default false\n */\n leading?: boolean;\n};\n\n/**\n * 创建一个防抖函数,该函数会在指定的等待时间后执行,如果在等待时间内再次调用,则重新计时。\n *\n * @param fn - 需要防抖的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait` 和 `leading` 选项的对象。\n * @returns 返回一个防抖函数,该函数具有 `cancel` 方法,用于取消防抖操作。\n *\n * @example\n * ```typescript\n * const debouncedFn = fnDebounce(() => {\n * console.log('Debounced!');\n * }, 100);\n *\n * debouncedFn(); // 不会立即执行\n * debouncedFn(); // 重新计时\n * debouncedFn.cancel(); // 取消防抖操作\n * ```\n */\nexport function fnDebounce<F extends AnyFunction>(fn: F, wait: number | DebounceOptions) {\n const options: DebounceOptions = isNumber(wait) ? { wait } : wait;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n let leading = false;\n\n const debounced = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n // 第一次执行\n if (options.leading && !leading) {\n leading = true;\n fn.apply(this, args);\n return;\n }\n\n // 最后一次执行\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (canceled) return;\n\n fn.apply(this, args);\n }, options.wait);\n };\n\n debounced.cancel = () => {\n clearTimeout(timer);\n canceled = true;\n };\n\n return debounced;\n}\n\nexport type ThrottleOptions = {\n /**\n * 等待时间(毫秒)。\n */\n wait: number;\n\n /**\n * 是否在第一次调用时立即执行\n * @default false\n */\n leading?: boolean;\n\n /**\n * 是否在调用结束后等待一段时间再执行\n * @default false\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个节流函数,该函数会在指定的等待时间内最多执行一次,如果在等待时间内再次调用,则忽略后续调用。\n *\n * @param fn - 需要节流的函数。\n * @param wait - 等待时间(毫秒)或包含 `wait`、`leading` 和 `trailing` 选项的对象。\n * @returns 返回一个节流函数,该函数具有 `cancel` 方法,用于取消节流操作。\n *\n * @example\n * ```typescript\n * const throttledFn = fnThrottle(() => {\n * console.log('Throttled!');\n * }, 100);\n *\n * throttledFn(); // 立即执行\n * throttledFn(); // 忽略\n * throttledFn.cancel(); // 取消节流操作\n * ```\n */\nexport function fnThrottle<F extends AnyFunction>(fn: F, wait: number | ThrottleOptions) {\n const options = isNumber(wait) ? { wait } : wait;\n const waitFinal = options.wait;\n let lastTime = 0;\n let canceled = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let timer: any;\n\n const throttled = function (this: unknown, ...args: Parameters<F>) {\n if (canceled) return;\n\n const now = Date.now();\n let executed = false;\n\n // 第一次执行\n if (options.leading && lastTime === 0) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 中间控频执行\n else if (lastTime > 0 && now - lastTime >= waitFinal) {\n lastTime = now;\n fn.apply(this, args);\n executed = true;\n }\n\n // 首次计时\n else if (lastTime === 0) {\n lastTime = now;\n }\n\n // 最后一次执行,仅在本次未执行时才设置 trailing\n if (options.trailing && !executed) {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn.apply(this, args);\n }, waitFinal);\n }\n };\n\n throttled.cancel = () => {\n canceled = true;\n clearTimeout(timer);\n };\n\n return throttled;\n}\n\n/**\n * 创建一个只执行一次的函数,无论调用多少次,实际执行的函数体也只会执行一次。\n *\n * @param fn - 需要只执行一次的函数。\n * @returns 返回一个只执行一次的函数,该函数在第一次调用后会缓存结果并返回缓存的结果。\n *\n * @example\n * ```typescript\n * const onceFn = fnOnce(() => {\n * console.log('This will be logged only once.');\n * return 42;\n * });\n *\n * console.log(onceFn()); // 输出: This will be logged only once. 42\n * console.log(onceFn()); // 输出: 42\n * ```\n */\nexport function fnOnce<F extends AnyFunction>(fn: F) {\n let called = false;\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let result: any;\n\n return function (this: unknown, ...args: Parameters<F>) {\n if (!called) {\n called = true;\n result = fn.apply(this, args);\n }\n\n return result;\n };\n}\n\nexport type FnRetryOptions = {\n /**\n * 最大尝试次数\n */\n maxAttempts?: number;\n /**\n * 每次重试之间的延迟时间(毫秒)\n * @default 0\n */\n delay?: number;\n /**\n * 自定义重试条件,返回 true 时触发重试\n * @default 仅在抛出错误时重试\n */\n retryWhen?: (error: unknown) => boolean;\n};\n\n/**\n * 创建一个带重试能力的函数,失败时自动重试直到成功或耗尽次数。\n *\n * @param fn - 需要重试的函数。\n * @param options - 重试配置选项。\n * @returns 返回一个带重试能力的函数。\n *\n * @example\n * ```typescript\n * const fetchData = fnRetry(async () => {\n * return await api.request('/data');\n * }, { maxAttempts: 3, delay: 1000 });\n *\n * // 第1次失败 → 等待1s → 第2次失败 → 等待1s → 第3次成功 → 返回结果\n * const result = await fetchData();\n * ```\n */\nexport function fnRetry<F extends AnyFunction>(fn: F, options: FnRetryOptions = {}) {\n const { maxAttempts = 3, delay = 0, retryWhen } = options;\n\n return async function (this: unknown, ...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return (await fn.apply(this, args)) as Awaited<ReturnType<F>>;\n } catch (error) {\n lastError = error;\n\n if (retryWhen && !retryWhen(error)) break;\n\n if (attempt < maxAttempts && delay > 0) {\n await promiseDelay(delay);\n }\n }\n }\n\n throw lastError;\n };\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,SAAS,CAEzB;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,WAAkC,IAAO,MAAgC;CACvF,MAAM,UAA2B,SAAS,IAAI,IAAI,EAAE,KAAK,IAAI;CAC7D,IAAI,WAAW;CAEf,IAAI;CACJ,IAAI,UAAU;CAEd,MAAM,YAAY,SAAyB,GAAG,MAAqB;EACjE,IAAI,UAAU;EAGd,IAAI,QAAQ,WAAW,CAAC,SAAS;GAC/B,UAAU;GACV,GAAG,MAAM,MAAM,IAAI;GACnB;EACF;EAGA,aAAa,KAAK;EAClB,QAAQ,iBAAiB;GACvB,IAAI,UAAU;GAEd,GAAG,MAAM,MAAM,IAAI;EACrB,GAAG,QAAQ,IAAI;CACjB;CAEA,UAAU,eAAe;EACvB,aAAa,KAAK;EAClB,WAAW;CACb;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,WAAkC,IAAO,MAAgC;CACvF,MAAM,UAAU,SAAS,IAAI,IAAI,EAAE,KAAK,IAAI;CAC5C,MAAM,YAAY,QAAQ;CAC1B,IAAI,WAAW;CACf,IAAI,WAAW;CAEf,IAAI;CAEJ,MAAM,YAAY,SAAyB,GAAG,MAAqB;EACjE,IAAI,UAAU;EAEd,MAAM,MAAM,KAAK,IAAI;EACrB,IAAI,WAAW;EAGf,IAAI,QAAQ,WAAW,aAAa,GAAG;GACrC,WAAW;GACX,GAAG,MAAM,MAAM,IAAI;GACnB,WAAW;EACb,OAGK,IAAI,WAAW,KAAK,MAAM,YAAY,WAAW;GACpD,WAAW;GACX,GAAG,MAAM,MAAM,IAAI;GACnB,WAAW;EACb,OAGK,IAAI,aAAa,GACpB,WAAW;EAIb,IAAI,QAAQ,YAAY,CAAC,UAAU;GACjC,aAAa,KAAK;GAClB,QAAQ,iBAAiB;IACvB,GAAG,MAAM,MAAM,IAAI;GACrB,GAAG,SAAS;EACd;CACF;CAEA,UAAU,eAAe;EACvB,WAAW;EACX,aAAa,KAAK;CACpB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,OAA8B,IAAO;CACnD,IAAI,SAAS;CAEb,IAAI;CAEJ,OAAO,SAAyB,GAAG,MAAqB;EACtD,IAAI,CAAC,QAAQ;GACX,SAAS;GACT,SAAS,GAAG,MAAM,MAAM,IAAI;EAC9B;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,QAA+B,IAAO,UAA0B,CAAC,GAAG;CAClF,MAAM,EAAE,cAAc,GAAG,QAAQ,GAAG,cAAc;CAElD,OAAO,eAA+B,GAAG,MAAsD;EAC7F,IAAI;EAEJ,KAAK,IAAI,UAAU,GAAG,WAAW,aAAa,WAC5C,IAAI;GACF,OAAQ,MAAM,GAAG,MAAM,MAAM,IAAI;EACnC,SAAS,OAAO;GACd,YAAY;GAEZ,IAAI,aAAa,CAAC,UAAU,KAAK,GAAG;GAEpC,IAAI,UAAU,eAAe,QAAQ,GACnC,MAAM,aAAa,KAAK;EAE5B;EAGF,MAAM;CACR;AACF"}
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/object.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.cjs","names":[],"sources":["../src/object/each.ts","../src/object/get-set.ts","../src/object/is.ts","../src/object/merge.ts","../src/object/process.ts"],"sourcesContent":["import type { AnyObject, MaybePromise } from '@/types';\n\n/**\n * 遍历对象的每个键值对,并对每个键值对执行提供的回调函数。\n *\n * @param obj - 要遍历的对象。\n * @param iterator - 对每个键值对执行的回调函数。如果回调函数返回 false,则提前终止遍历。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const results: [string, number][] = [];\n * objectEach(obj, (val, key) => {\n * results.push([key, val]);\n * });\n * console.log(results); // [['a', 1], ['b', 2], ['c', 3]]\n * ```\n */\nexport function objectEach<O extends AnyObject, K extends keyof O & (string | number)>(\n obj: O,\n iterator: (this: O, val: O[K], key: K) => false | unknown,\n): void {\n for (const [key, val] of Object.entries(obj)) {\n if (iterator.call(obj, val as O[K], key as K) === false) {\n break;\n }\n }\n}\n\n/**\n * 异步遍历对象的每个键值对,并对每个键值对执行提供的回调函数。\n *\n * @param obj - 要遍历的对象。\n * @param iterator - 对每个键值对执行的异步回调函数。如果回调函数返回 false,则提前终止遍历。\n * @returns 返回一个 Promise,当所有异步操作完成后,Promise 会被 resolve。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const results: [string, number][] = [];\n * await objectEachAsync(obj, async (val, key) => {\n * results.push([key, val]);\n * });\n * console.log(results); // [['a', 1], ['b', 2], ['c', 3]]\n * ```\n */\nexport async function objectEachAsync<O extends AnyObject, K extends keyof O & (string | number)>(\n obj: O,\n iterator: (this: O, val: O[K], key: K) => MaybePromise<false | unknown>,\n): Promise<void> {\n for (const [key, val] of Object.entries(obj)) {\n if ((await iterator.call(obj, val as O[K], key as K)) === false) {\n break;\n }\n }\n}\n","import { isArray, isObject, isUndefined } from '@/type';\nimport type { AnyArray, AnyObject } from '@/types';\n\n// @ref https://stackoverflow.com/a/67609485\n\ntype Idx<T, K> = K extends keyof T\n ? T[K]\n : number extends keyof T\n ? K extends `${number}`\n ? T[number]\n : never\n : never;\n\ntype Join<K, P> = K extends string | number\n ? P extends string | number\n ? `${K}${'' extends P ? '' : '.'}${P}`\n : never\n : never;\n\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n\nexport type ObjectPath<O, D extends number = 4> = [D] extends [never]\n ? never\n : O extends object\n ? {\n [K in keyof O]-?: K extends string | number ? `${K}` | Join<K, ObjectPath<O[K], Prev[D]>> : never;\n }[keyof O]\n : '';\n\nexport type ObjectLeafPath<O, D extends number = 4> = [D] extends [never]\n ? never\n : O extends object\n ? {\n [K in keyof O]-?: K extends string | number\n ? O[K] extends string | number\n ? `${K}` | Join<K, ObjectLeafPath<O[K], Prev[D]>>\n : Join<K, ObjectLeafPath<O[K], Prev[D]>>\n : never;\n }[keyof O]\n : '';\n\nexport type ObjectPathValue<O, P extends ObjectPath<O, 4>> = P extends `${infer Key}.${infer Rest}`\n ? Rest extends ObjectPath<Idx<O, Key>, 4>\n ? ObjectPathValue<Idx<O, Key>, Rest>\n : never\n : Idx<O, P>;\n\nfunction pathToKeys(path: string | string[]) {\n // 下文用到该数组时会进行修改操作,因此复制一份\n if (isArray(path)) return [...path];\n\n let pathFinal = path.replace(/\\[(\\w+)\\]/g, '.$1');\n pathFinal = pathFinal.replace(/^\\./, '');\n return pathFinal.split('.');\n}\n\nfunction isObjectOrArray(v: unknown) {\n return isObject(v) || isArray(v);\n}\n\n/**\n * 表示对象节点的信息。\n *\n * @template V - 键值的类型。\n */\nexport type ObjectNode<V = unknown | undefined> = {\n /**\n * 当前节点的父级对象。\n */\n parent: unknown | undefined;\n\n /**\n * 当前节点的键名路径。\n */\n keys: string[];\n\n /**\n * 当前节点的键名。\n */\n key: string | undefined;\n\n /**\n * 当前节点的键值。\n */\n value: V;\n};\n\n/**\n * 根据属性路径获取属性值\n * @param {O} obj\n * @param {string | string[] | P} path\n * @returns {ObjectNode<O>}\n * 根据属性路径获取属性值。\n *\n * @template O - 目标对象的类型。\n * @template P - 属性路径的类型。\n * @param {O} obj - 要操作的目标对象。\n * @param {P | string | string[]} path - 属性路径,可以是字符串或字符串数组。支持点分隔符(如 \"a.b.c\")或数组形式(如 [\"a\", \"b\", \"c\"])。\n * @returns {ObjectNode<O>} 返回一个包含父级、键名路径、键名和键值的对象节点。\n *\n * @example\n * ```typescript\n * const obj = { a: { b: { c: 42 } } };\n * const result = objectGet(obj, 'a.b.c');\n * console.log(result.value); // 输出 42\n * ```\n */\nexport function objectGet<O extends AnyObject, P extends ObjectPath<O>>(\n obj: O,\n path: P | string | string[],\n): ObjectNode<O> {\n const keys = pathToKeys(path);\n const lastKey = keys.pop();\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let parent: any = obj;\n const keysFinal: string[] = [];\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n\n keysFinal.push(key);\n if (!isObjectOrArray(parent)) break;\n\n // @ts-expect-error\n parent = parent[key];\n }\n\n return {\n parent: parent,\n keys: keysFinal,\n key: lastKey,\n // @ts-expect-error\n value: isObjectOrArray(parent) && lastKey ? parent[lastKey] : undefined,\n };\n}\n\n// /**\n// * 根据路径获取对象叶子节点值\n// * @param {O} obj\n// * @param {P} path\n// * @returns {ObjectNode<O>}\n// */\n// export function objectLeaf<O extends AnyObject, P extends ObjectLeafPath<O>>(obj: O, path: P) {\n// return objectGet(obj, path);\n// }\n\n/**\n * 配置选项,用于控制 `objectSet` 的行为。\n *\n * @template O - 目标对象的类型。\n */\nexport type ObjectSetOptions<O extends AnyObject> = {\n /**\n * 在设置值之前调用的钩子函数。\n * 如果返回 `false`,则阻止设置值。\n *\n * @param {ObjectNode<O> & { key: string }} node - 当前节点信息。\n * @returns {boolean | undefined | void} 返回 `false` 时阻止设置值。\n */\n beforeSet(node: ObjectNode<O> & { key: string }): boolean | undefined;\n\n /**\n * 当遇到未定义的中间节点时调用的钩子函数。\n * 返回值将用于创建中间节点。\n *\n * @param {ObjectNode<O>} node - 当前节点信息。\n * @returns {AnyObject | AnyArray | undefined | void} 返回值将用于创建中间节点。\n */\n undefinedSet(node: ObjectNode<O>): AnyObject | AnyArray | undefined;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: 内部使用 any\nconst defaultObjectSetOptions: ObjectSetOptions<any> = {\n beforeSet: () => true,\n undefinedSet: () => ({}),\n};\n\n/**\n * 根据属性路径设置属性值\n * @param {AnyObject} obj\n * @param {string} path\n * @param {V} val\n * @param {Partial<ObjectSetOptions<O>>} options\n * @returns {ObjectNode<O, V>}\n * 根据属性路径设置属性值。\n *\n * @template O - 目标对象的类型。\n * @template V - 要设置的值的类型。\n * @param {O} obj - 要操作的目标对象。\n * @param {string | string[]} path - 属性路径,可以是字符串或字符串数组。支持点分隔符(如 \"a.b.c\")或数组形式(如 [\"a\", \"b\", \"c\"])。\n * @param {V} val - 要设置的值。\n * @param {Partial<ObjectSetOptions<O>>} [options] - 可选配置项,用于控制设置行为。\n * @returns {ObjectNode<V>} 返回一个包含父级、键名路径、键名和键值的对象节点。\n *\n * @example\n * ```typescript\n * const obj = {};\n * objectSet(obj, 'a.b.c', 42);\n * console.log(obj); // 输出 { a: { b: { c: 42 } } }\n *\n * objectSet(obj, 'a.b.c', 100, {\n * beforeSet: (node) => node.key === 'c',\n * });\n * console.log(obj); // 输出 { a: { b: { c: 100 } } }\n * ```\n */\nexport function objectSet<O extends AnyObject, V>(\n obj: O,\n path: string | string[],\n val: V,\n options?: Partial<ObjectSetOptions<O>>,\n): ObjectNode<V> {\n const { beforeSet, undefinedSet } = Object.assign({}, defaultObjectSetOptions, options);\n const keys = pathToKeys(path);\n const lastKey = keys.pop();\n let parent = obj;\n let stopped = false;\n const keysFinal: string[] = [];\n\n for (const key of keys) {\n let val = parent[key];\n keysFinal.push(key);\n\n if (isUndefined(val)) {\n const seted = undefinedSet({\n parent: parent,\n keys: keysFinal,\n key: key,\n value: val,\n });\n\n if (!seted) {\n stopped = true;\n break;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n val = parent[key] = seted;\n }\n\n // @ts-expect-error\n parent = val;\n }\n\n if (!stopped && !isUndefined(lastKey)) {\n keysFinal.push(lastKey);\n\n if (\n beforeSet({\n parent: parent,\n keys: keysFinal,\n key: lastKey,\n value: parent[lastKey],\n })\n ) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n parent[lastKey] = val;\n }\n }\n\n return {\n keys: keysFinal,\n parent: parent,\n key: lastKey,\n value: val,\n };\n}\n","import type { AnyObject } from '@/types';\n\n/**\n * 检查一个对象是否为空对象(不包含任何自有属性,包括符号属性)。\n *\n * @param obj - 要检查的对象\n * @returns 如果对象没有自有属性(包括符号属性)则返回 true,否则返回 false\n *\n * @example\n * ```typescript\n * isEmptyObject({}); // true\n * isEmptyObject({ a: 1 }); // false\n * isEmptyObject(Object.create(null)); // true\n * isEmptyObject({ [Symbol('key')]: 'value' }); // false\n * ```\n */\nexport function isEmptyObject(obj: AnyObject): boolean {\n return Object.getOwnPropertyNames(obj).length === 0 && Object.getOwnPropertySymbols(obj).length === 0;\n}\n\n/**\n * 检查一个对象是否为纯对象(通过对象字面量或Object构造函数创建,而非其他构造函数的实例)。\n *\n * @param obj - 要检查的对象\n * @returns 如果是纯对象则返回 true,否则返回 false\n *\n * @example\n * ```typescript\n * isPlainObject({}); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(new Date()); // false\n * isPlainObject([]); // false\n * isPlainObject(() => {}); // false\n * ```\n */\nexport function isPlainObject(obj: AnyObject): boolean {\n const proto: unknown = Object.getPrototypeOf(obj);\n\n // 对象无原型\n if (!proto) return true;\n\n // 是否对象直接实例\n return proto === Object.prototype;\n}\n\n// 移除,原因是,定义对象尽可能的使用 type 关键字即可避开此问题\n// /**\n// * 精确对象,常用于联合类型判断\n// * 相关 bug:https://l.ydr.me/Zp88vFKc\n// */\n// // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n// export type ExactObject<T = any> = T extends AnyFunction\n// ? never\n// : T extends AnyArray\n// ? never\n// : T extends object\n// ? T\n// : never;\n//\n// /**\n// * 检查值是否为精确接口对象\n// * @param object - 传入对象,必须是一个对象与其他类型的联合\n// * @returns 如果值为对象则返回 true,否则返回 false\n// * @example\n// * ```typescript\n// * type Id = string | string[] | (() => string);\n// *\n// * interface Cache {\n// * id?: Id;\n// * }\n// *\n// * type Share = {\n// * id?: Id;\n// * }\n// *\n// * interface Options {\n// * cache?: Id | Cache;\n// * share?: Id | Share;\n// * }\n// *\n// * function test(options: Options) {\n// * // string | string[] | (() => string) | Cache | undefined\n// * const cache = options.cache;\n// *\n// * // Cache\n// * // 需要使用\n// * if (isExactObject(cache)) {\n// * cache.id;\n// * }\n// * // string[]\n// * else if (isArray(cache)) {\n// * cache.push();\n// * }\n// * // string\n// * else if (isString(cache)) {\n// * cache.charCodeAt(0);\n// * }\n// * // (() => string) | undefined\n// * else {\n// * cache?.();\n// * }\n// *\n// * // string | string[] | (() => string) | Share | undefined\n// * const share = options.share;\n// *\n// * // Share\n// * if (isObject(share)) {\n// * share.id;\n// * }\n// * // string[]\n// * else if (isArray(share)) {\n// * share.push();\n// * }\n// * // string\n// * else if (isString(share)) {\n// * share.charCodeAt(0);\n// * }\n// * // (() => string) | undefined\n// * else {\n// * share?.();\n// * }\n// * }\n// * ```\n// */\n// export function isExactObject<T>(object: T): object is ExactObject<T> {\n// return typeIs(object) === 'object';\n// }\n","import { isArray, isObject, typeIs } from '@/type';\nimport type { AnyArray, AnyObject } from '@/types';\nimport { objectEach } from './each';\n\nexport type ObjectMergeRule = {\n /**\n * 处理冲突\n * @param target - 目标对象\n * @param source - 源对象\n * @param key - 键名\n * @returns 返回 true 表示继续处理,否则返回 false\n */\n next: (info: { target: AnyObject | AnyArray; source: AnyObject | AnyArray; key: string | number }) => boolean;\n\n /**\n * 处理赋值\n * @param target - 目标对象\n * @param source - 源对象\n * @param key - 键名\n * @returns 返回处理后的值\n */\n assign: (info: {\n target: AnyObject | AnyArray;\n source: AnyObject | AnyArray;\n key: string | number;\n merge: () => unknown;\n }) => unknown;\n};\n\nfunction _objectMerge(mergeRule: ObjectMergeRule, target: AnyObject | AnyArray, ...sources: (AnyObject | AnyArray)[]) {\n const seen = new WeakMap<AnyObject | AnyArray, AnyObject | AnyArray>();\n const { assign, next } = mergeRule;\n const align = (target: AnyObject | AnyArray, source: AnyObject | AnyArray) => {\n const targetType = typeIs(target);\n const sourceType = typeIs(source);\n\n if (targetType === sourceType) {\n return target;\n }\n\n return sourceType === 'array' ? [] : {};\n };\n const each = (\n source: AnyObject | AnyArray,\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用 any\n iterator: (val: any, key: string | number) => void,\n ) => {\n if (isObject(source)) {\n objectEach(source, iterator);\n } else {\n source.forEach(iterator);\n }\n };\n\n const merge = (target: AnyObject | AnyArray, source: AnyObject | AnyArray): AnyObject | AnyArray => {\n // 如果循环引用了,则直接返回目标对象\n if (seen.has(source)) {\n // biome-ignore lint/style/noNonNullAssertion: 必须存在\n return seen.get(source)!;\n }\n\n // 对齐目标对象和源对象\n const merged = align(target, source);\n\n // 存储循环引用\n seen.set(source, merged);\n\n // 遍历源对象\n each(source, (value, key) => {\n if (!next({ target: merged, source, key })) {\n return;\n }\n\n if (isObject(value) || isArray(value)) {\n // @ts-expect-error\n merged[key] = assign({\n target: merged,\n source,\n key,\n // @ts-expect-error\n merge: () => merge(merged[key], value),\n });\n } else {\n // @ts-expect-error\n merged[key] = assign({\n target: merged,\n source,\n key,\n merge: () => value,\n });\n }\n });\n\n return merged;\n };\n\n let returnTarget = target;\n\n for (const source of sources) {\n returnTarget = merge(target, source);\n }\n\n return returnTarget;\n}\n\n/**\n * 合并多个对象或数组。如果遇到循环引用,则直接返回目标对象。\n *\n * @param target - 目标对象或数组。\n * @param sources - 要合并的源对象或数组。\n * @returns 合并后的对象或数组。\n *\n * @example\n * ```typescript\n * const obj1 = { a: 1, b: { x: 10 } };\n * const obj2 = { b: { y: 20 }, c: 3 };\n * const merged = objectMerge(obj1, obj2);\n * console.log(merged); // { a: 1, b: { x: 10, y: 20 }, c: 3 }\n * ```\n */\nexport function objectMerge(target: AnyObject | AnyArray, ...sources: (AnyObject | AnyArray)[]) {\n return _objectMerge(\n {\n next() {\n return true;\n },\n assign({ merge }) {\n return merge();\n },\n },\n target,\n ...sources,\n );\n}\n\n/**\n * 为对象设置默认值。如果目标对象中的属性为 `undefined`,则使用默认对象中的属性值。\n * 支持多个默认对象,优先级从左到右依次降低。\n * 如果目标对象中的属性已经是对象或数组,则递归地设置默认值。\n *\n * @param target - 目标对象或数组。\n * @param defaults - 默认对象或数组。\n * @returns 合并后的对象或数组。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: undefined };\n * const defaults = { a: 4, b: 2, c: 3 };\n * const result = objectDefaults(obj, defaults);\n * console.log(result); // { a: 1, b: 2, c: 3 }\n *\n * const obj2 = { a: 1, b: 2 };\n * const defaults2 = { a: 5, b: 3, c: 4 };\n * const result2 = objectDefaults(obj2, defaults2);\n * console.log(result2); // { a: 1, b: 2, c: 4 }\n *\n * const obj3 = { a: { x: 1 }, b: undefined };\n * const defaults3 = { a: { x: 4, z: 3 }, b: { y: 2 } };\n * const result3 = objectDefaults(obj3, defaults3);\n * console.log(result3); // { a: { x: 1, z: 3 }, b: { y: 2 } }\n * ```\n */\nexport function objectDefaults<T extends AnyObject | AnyArray>(target: T, defaults: T): T {\n return _objectMerge(\n {\n next({ target, key }) {\n return (\n // @ts-expect-error\n target[key] === undefined ||\n // @ts-expect-error\n isObject(target[key]) ||\n // @ts-expect-error\n isArray(target[key])\n );\n },\n assign({ merge }) {\n return merge();\n },\n },\n target,\n defaults,\n ) as T;\n}\n","import type { AnyObject } from '@/types';\n\n/**\n * 从对象中选择指定键的属性,返回一个新的对象。\n *\n * @param object - 要从中选择属性的对象。\n * @param keys - 要选择的键数组。\n * @returns 包含指定键属性的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const result = objectPick(obj, ['a', 'c']);\n * console.log(result); // { a: 1, c: 3 }\n * ```\n */\nexport function objectPick<T extends AnyObject, K extends keyof T>(object: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (key in object) {\n result[key] = object[key];\n }\n }\n return result;\n}\n\n/**\n * 从对象中排除指定键的属性,返回一个新的对象。\n *\n * @param object - 要从中排除属性的对象。\n * @param keys - 要排除的键数组。\n * @returns 排除指定键属性后的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3, d: 4 };\n * const result = objectOmit(obj, ['a', 'd']);\n * console.log(result); // { b: 2, c: 3 }\n * ```\n */\nexport function objectOmit<T extends AnyObject, K extends keyof T>(object: T, keys: K[]): Omit<T, K> {\n const result = {} as Omit<T, K>;\n for (const key in object) {\n if (!keys.includes(key as unknown as K)) {\n // @ts-expect-error\n result[key] = object[key];\n }\n }\n return result;\n}\n\n/**\n * 遍历对象的每个键值对,并对每个键值对执行提供的映射函数,返回一个新的对象。\n *\n * @param object - 要遍历的对象。\n * @param mapper - 对每个键值对执行的映射函数。\n * @returns 返回一个新的对象,其中每个值都是通过映射函数处理后的结果。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const result = objectMap(obj, (val, key) => String(val * 2));\n * console.log(result); // { a: '2', b: '4', c: '6' }\n * ```\n */\nexport function objectMap<T extends AnyObject, V>(\n object: T,\n mapper: (value: T[keyof T], key: keyof T) => V,\n): Record<keyof T, V> {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [\n key,\n mapper(\n // @ts-expect-error\n value,\n key as keyof T,\n ),\n ]),\n ) as Record<keyof T, V>;\n}\n\n/**\n * 根据提供的过滤函数过滤对象的属性,返回一个新对象,只包含满足条件的属性。\n *\n * @param object - 要过滤的对象。\n * @param predicate - 过滤函数,接收值和键作为参数,返回布尔值。\n * @returns 包含满足过滤条件的属性的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3, d: 4 };\n * const result = objectFilter(obj, (value, key) => value > 2);\n * console.log(result); // { c: 3, d: 4 }\n * ```\n */\nexport function objectFilter<T extends AnyObject>(\n object: T,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> {\n return Object.fromEntries(\n Object.entries(object).filter(([key, value]) => predicate(value as T[keyof T], key as keyof T)),\n ) as Partial<T>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"object.cjs","names":[],"sources":["../src/object/each.ts","../src/object/get-set.ts","../src/object/is.ts","../src/object/merge.ts","../src/object/process.ts"],"sourcesContent":["import type { AnyObject, MaybePromise } from '@/types';\n\n/**\n * 遍历对象的每个键值对,并对每个键值对执行提供的回调函数。\n *\n * @param obj - 要遍历的对象。\n * @param iterator - 对每个键值对执行的回调函数。如果回调函数返回 false,则提前终止遍历。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const results: [string, number][] = [];\n * objectEach(obj, (val, key) => {\n * results.push([key, val]);\n * });\n * console.log(results); // [['a', 1], ['b', 2], ['c', 3]]\n * ```\n */\nexport function objectEach<O extends AnyObject, K extends keyof O & (string | number)>(\n obj: O,\n iterator: (this: O, val: O[K], key: K) => false | unknown,\n): void {\n for (const [key, val] of Object.entries(obj)) {\n if (iterator.call(obj, val as O[K], key as K) === false) {\n break;\n }\n }\n}\n\n/**\n * 异步遍历对象的每个键值对,并对每个键值对执行提供的回调函数。\n *\n * @param obj - 要遍历的对象。\n * @param iterator - 对每个键值对执行的异步回调函数。如果回调函数返回 false,则提前终止遍历。\n * @returns 返回一个 Promise,当所有异步操作完成后,Promise 会被 resolve。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const results: [string, number][] = [];\n * await objectEachAsync(obj, async (val, key) => {\n * results.push([key, val]);\n * });\n * console.log(results); // [['a', 1], ['b', 2], ['c', 3]]\n * ```\n */\nexport async function objectEachAsync<O extends AnyObject, K extends keyof O & (string | number)>(\n obj: O,\n iterator: (this: O, val: O[K], key: K) => MaybePromise<false | unknown>,\n): Promise<void> {\n for (const [key, val] of Object.entries(obj)) {\n if ((await iterator.call(obj, val as O[K], key as K)) === false) {\n break;\n }\n }\n}\n","import { isArray, isObject, isUndefined } from '@/type';\nimport type { AnyArray, AnyObject } from '@/types';\n\n// @ref https://stackoverflow.com/a/67609485\n\ntype Idx<T, K> = K extends keyof T\n ? T[K]\n : number extends keyof T\n ? K extends `${number}`\n ? T[number]\n : never\n : never;\n\ntype Join<K, P> = K extends string | number\n ? P extends string | number\n ? `${K}${'' extends P ? '' : '.'}${P}`\n : never\n : never;\n\ntype Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];\n\nexport type ObjectPath<O, D extends number = 4> = [D] extends [never]\n ? never\n : O extends object\n ? {\n [K in keyof O]-?: K extends string | number ? `${K}` | Join<K, ObjectPath<O[K], Prev[D]>> : never;\n }[keyof O]\n : '';\n\nexport type ObjectLeafPath<O, D extends number = 4> = [D] extends [never]\n ? never\n : O extends object\n ? {\n [K in keyof O]-?: K extends string | number\n ? O[K] extends string | number\n ? `${K}` | Join<K, ObjectLeafPath<O[K], Prev[D]>>\n : Join<K, ObjectLeafPath<O[K], Prev[D]>>\n : never;\n }[keyof O]\n : '';\n\nexport type ObjectPathValue<O, P extends ObjectPath<O, 4>> = P extends `${infer Key}.${infer Rest}`\n ? Rest extends ObjectPath<Idx<O, Key>, 4>\n ? ObjectPathValue<Idx<O, Key>, Rest>\n : never\n : Idx<O, P>;\n\nfunction pathToKeys(path: string | string[]) {\n // 下文用到该数组时会进行修改操作,因此复制一份\n if (isArray(path)) return [...path];\n\n let pathFinal = path.replace(/\\[(\\w+)\\]/g, '.$1');\n pathFinal = pathFinal.replace(/^\\./, '');\n return pathFinal.split('.');\n}\n\nfunction isObjectOrArray(v: unknown) {\n return isObject(v) || isArray(v);\n}\n\n/**\n * 表示对象节点的信息。\n *\n * @template V - 键值的类型。\n */\nexport type ObjectNode<V = unknown | undefined> = {\n /**\n * 当前节点的父级对象。\n */\n parent: unknown | undefined;\n\n /**\n * 当前节点的键名路径。\n */\n keys: string[];\n\n /**\n * 当前节点的键名。\n */\n key: string | undefined;\n\n /**\n * 当前节点的键值。\n */\n value: V;\n};\n\n/**\n * 根据属性路径获取属性值\n * @param {O} obj\n * @param {string | string[] | P} path\n * @returns {ObjectNode<O>}\n * 根据属性路径获取属性值。\n *\n * @template O - 目标对象的类型。\n * @template P - 属性路径的类型。\n * @param {O} obj - 要操作的目标对象。\n * @param {P | string | string[]} path - 属性路径,可以是字符串或字符串数组。支持点分隔符(如 \"a.b.c\")或数组形式(如 [\"a\", \"b\", \"c\"])。\n * @returns {ObjectNode<O>} 返回一个包含父级、键名路径、键名和键值的对象节点。\n *\n * @example\n * ```typescript\n * const obj = { a: { b: { c: 42 } } };\n * const result = objectGet(obj, 'a.b.c');\n * console.log(result.value); // 输出 42\n * ```\n */\nexport function objectGet<O extends AnyObject, P extends ObjectPath<O>>(\n obj: O,\n path: P | string | string[],\n): ObjectNode<O> {\n const keys = pathToKeys(path);\n const lastKey = keys.pop();\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用\n let parent: any = obj;\n const keysFinal: string[] = [];\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n\n keysFinal.push(key);\n if (!isObjectOrArray(parent)) break;\n\n // @ts-expect-error\n parent = parent[key];\n }\n\n return {\n parent: parent,\n keys: keysFinal,\n key: lastKey,\n // @ts-expect-error\n value: isObjectOrArray(parent) && lastKey ? parent[lastKey] : undefined,\n };\n}\n\n// /**\n// * 根据路径获取对象叶子节点值\n// * @param {O} obj\n// * @param {P} path\n// * @returns {ObjectNode<O>}\n// */\n// export function objectLeaf<O extends AnyObject, P extends ObjectLeafPath<O>>(obj: O, path: P) {\n// return objectGet(obj, path);\n// }\n\n/**\n * 配置选项,用于控制 `objectSet` 的行为。\n *\n * @template O - 目标对象的类型。\n */\nexport type ObjectSetOptions<O extends AnyObject> = {\n /**\n * 在设置值之前调用的钩子函数。\n * 如果返回 `false`,则阻止设置值。\n *\n * @param {ObjectNode<O> & { key: string }} node - 当前节点信息。\n * @returns {boolean | undefined | void} 返回 `false` 时阻止设置值。\n */\n beforeSet(node: ObjectNode<O> & { key: string }): boolean | undefined;\n\n /**\n * 当遇到未定义的中间节点时调用的钩子函数。\n * 返回值将用于创建中间节点。\n *\n * @param {ObjectNode<O>} node - 当前节点信息。\n * @returns {AnyObject | AnyArray | undefined | void} 返回值将用于创建中间节点。\n */\n undefinedSet(node: ObjectNode<O>): AnyObject | AnyArray | undefined;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: 内部使用 any\nconst defaultObjectSetOptions: ObjectSetOptions<any> = {\n beforeSet: () => true,\n undefinedSet: () => ({}),\n};\n\n/**\n * 根据属性路径设置属性值\n * @param {AnyObject} obj\n * @param {string} path\n * @param {V} val\n * @param {Partial<ObjectSetOptions<O>>} options\n * @returns {ObjectNode<O, V>}\n * 根据属性路径设置属性值。\n *\n * @template O - 目标对象的类型。\n * @template V - 要设置的值的类型。\n * @param {O} obj - 要操作的目标对象。\n * @param {string | string[]} path - 属性路径,可以是字符串或字符串数组。支持点分隔符(如 \"a.b.c\")或数组形式(如 [\"a\", \"b\", \"c\"])。\n * @param {V} val - 要设置的值。\n * @param {Partial<ObjectSetOptions<O>>} [options] - 可选配置项,用于控制设置行为。\n * @returns {ObjectNode<V>} 返回一个包含父级、键名路径、键名和键值的对象节点。\n *\n * @example\n * ```typescript\n * const obj = {};\n * objectSet(obj, 'a.b.c', 42);\n * console.log(obj); // 输出 { a: { b: { c: 42 } } }\n *\n * objectSet(obj, 'a.b.c', 100, {\n * beforeSet: (node) => node.key === 'c',\n * });\n * console.log(obj); // 输出 { a: { b: { c: 100 } } }\n * ```\n */\nexport function objectSet<O extends AnyObject, V>(\n obj: O,\n path: string | string[],\n val: V,\n options?: Partial<ObjectSetOptions<O>>,\n): ObjectNode<V> {\n const { beforeSet, undefinedSet } = Object.assign({}, defaultObjectSetOptions, options);\n const keys = pathToKeys(path);\n const lastKey = keys.pop();\n let parent = obj;\n let stopped = false;\n const keysFinal: string[] = [];\n\n for (const key of keys) {\n let val = parent[key];\n keysFinal.push(key);\n\n if (isUndefined(val)) {\n const seted = undefinedSet({\n parent: parent,\n keys: keysFinal,\n key: key,\n value: val,\n });\n\n if (!seted) {\n stopped = true;\n break;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n val = parent[key] = seted;\n }\n\n // @ts-expect-error\n parent = val;\n }\n\n if (!stopped && !isUndefined(lastKey)) {\n keysFinal.push(lastKey);\n\n if (\n beforeSet({\n parent: parent,\n keys: keysFinal,\n key: lastKey,\n value: parent[lastKey],\n })\n ) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n parent[lastKey] = val;\n }\n }\n\n return {\n keys: keysFinal,\n parent: parent,\n key: lastKey,\n value: val,\n };\n}\n","import type { AnyObject } from '@/types';\n\n/**\n * 检查一个对象是否为空对象(不包含任何自有属性,包括符号属性)。\n *\n * @param obj - 要检查的对象\n * @returns 如果对象没有自有属性(包括符号属性)则返回 true,否则返回 false\n *\n * @example\n * ```typescript\n * isEmptyObject({}); // true\n * isEmptyObject({ a: 1 }); // false\n * isEmptyObject(Object.create(null)); // true\n * isEmptyObject({ [Symbol('key')]: 'value' }); // false\n * ```\n */\nexport function isEmptyObject(obj: AnyObject): boolean {\n return Object.getOwnPropertyNames(obj).length === 0 && Object.getOwnPropertySymbols(obj).length === 0;\n}\n\n/**\n * 检查一个对象是否为纯对象(通过对象字面量或Object构造函数创建,而非其他构造函数的实例)。\n *\n * @param obj - 要检查的对象\n * @returns 如果是纯对象则返回 true,否则返回 false\n *\n * @example\n * ```typescript\n * isPlainObject({}); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(new Date()); // false\n * isPlainObject([]); // false\n * isPlainObject(() => {}); // false\n * ```\n */\nexport function isPlainObject(obj: AnyObject): boolean {\n const proto: unknown = Object.getPrototypeOf(obj);\n\n // 对象无原型\n if (!proto) return true;\n\n // 是否对象直接实例\n return proto === Object.prototype;\n}\n\n// 移除,原因是,定义对象尽可能的使用 type 关键字即可避开此问题\n// /**\n// * 精确对象,常用于联合类型判断\n// * 相关 bug:https://l.ydr.me/Zp88vFKc\n// */\n// // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n// export type ExactObject<T = any> = T extends AnyFunction\n// ? never\n// : T extends AnyArray\n// ? never\n// : T extends object\n// ? T\n// : never;\n//\n// /**\n// * 检查值是否为精确接口对象\n// * @param object - 传入对象,必须是一个对象与其他类型的联合\n// * @returns 如果值为对象则返回 true,否则返回 false\n// * @example\n// * ```typescript\n// * type Id = string | string[] | (() => string);\n// *\n// * interface Cache {\n// * id?: Id;\n// * }\n// *\n// * type Share = {\n// * id?: Id;\n// * }\n// *\n// * interface Options {\n// * cache?: Id | Cache;\n// * share?: Id | Share;\n// * }\n// *\n// * function test(options: Options) {\n// * // string | string[] | (() => string) | Cache | undefined\n// * const cache = options.cache;\n// *\n// * // Cache\n// * // 需要使用\n// * if (isExactObject(cache)) {\n// * cache.id;\n// * }\n// * // string[]\n// * else if (isArray(cache)) {\n// * cache.push();\n// * }\n// * // string\n// * else if (isString(cache)) {\n// * cache.charCodeAt(0);\n// * }\n// * // (() => string) | undefined\n// * else {\n// * cache?.();\n// * }\n// *\n// * // string | string[] | (() => string) | Share | undefined\n// * const share = options.share;\n// *\n// * // Share\n// * if (isObject(share)) {\n// * share.id;\n// * }\n// * // string[]\n// * else if (isArray(share)) {\n// * share.push();\n// * }\n// * // string\n// * else if (isString(share)) {\n// * share.charCodeAt(0);\n// * }\n// * // (() => string) | undefined\n// * else {\n// * share?.();\n// * }\n// * }\n// * ```\n// */\n// export function isExactObject<T>(object: T): object is ExactObject<T> {\n// return typeIs(object) === 'object';\n// }\n","import { isArray, isObject, typeIs } from '@/type';\nimport type { AnyArray, AnyObject } from '@/types';\nimport { objectEach } from './each';\n\nexport type ObjectMergeRule = {\n /**\n * 处理冲突\n * @param target - 目标对象\n * @param source - 源对象\n * @param key - 键名\n * @returns 返回 true 表示继续处理,否则返回 false\n */\n next: (info: { target: AnyObject | AnyArray; source: AnyObject | AnyArray; key: string | number }) => boolean;\n\n /**\n * 处理赋值\n * @param target - 目标对象\n * @param source - 源对象\n * @param key - 键名\n * @returns 返回处理后的值\n */\n assign: (info: {\n target: AnyObject | AnyArray;\n source: AnyObject | AnyArray;\n key: string | number;\n merge: () => unknown;\n }) => unknown;\n};\n\nfunction _objectMerge(mergeRule: ObjectMergeRule, target: AnyObject | AnyArray, ...sources: (AnyObject | AnyArray)[]) {\n const seen = new WeakMap<AnyObject | AnyArray, AnyObject | AnyArray>();\n const { assign, next } = mergeRule;\n const align = (target: AnyObject | AnyArray, source: AnyObject | AnyArray) => {\n const targetType = typeIs(target);\n const sourceType = typeIs(source);\n\n if (targetType === sourceType) {\n return target;\n }\n\n return sourceType === 'array' ? [] : {};\n };\n const each = (\n source: AnyObject | AnyArray,\n // biome-ignore lint/suspicious/noExplicitAny: 内部使用 any\n iterator: (val: any, key: string | number) => void,\n ) => {\n if (isObject(source)) {\n objectEach(source, iterator);\n } else {\n source.forEach(iterator);\n }\n };\n\n const merge = (target: AnyObject | AnyArray, source: AnyObject | AnyArray): AnyObject | AnyArray => {\n // 如果循环引用了,则直接返回目标对象\n if (seen.has(source)) {\n // biome-ignore lint/style/noNonNullAssertion: 必须存在\n return seen.get(source)!;\n }\n\n // 对齐目标对象和源对象\n const merged = align(target, source);\n\n // 存储循环引用\n seen.set(source, merged);\n\n // 遍历源对象\n each(source, (value, key) => {\n if (!next({ target: merged, source, key })) {\n return;\n }\n\n if (isObject(value) || isArray(value)) {\n // @ts-expect-error\n merged[key] = assign({\n target: merged,\n source,\n key,\n // @ts-expect-error\n merge: () => merge(merged[key], value),\n });\n } else {\n // @ts-expect-error\n merged[key] = assign({\n target: merged,\n source,\n key,\n merge: () => value,\n });\n }\n });\n\n return merged;\n };\n\n let returnTarget = target;\n\n for (const source of sources) {\n returnTarget = merge(target, source);\n }\n\n return returnTarget;\n}\n\n/**\n * 合并多个对象或数组。如果遇到循环引用,则直接返回目标对象。\n *\n * @param target - 目标对象或数组。\n * @param sources - 要合并的源对象或数组。\n * @returns 合并后的对象或数组。\n *\n * @example\n * ```typescript\n * const obj1 = { a: 1, b: { x: 10 } };\n * const obj2 = { b: { y: 20 }, c: 3 };\n * const merged = objectMerge(obj1, obj2);\n * console.log(merged); // { a: 1, b: { x: 10, y: 20 }, c: 3 }\n * ```\n */\nexport function objectMerge(target: AnyObject | AnyArray, ...sources: (AnyObject | AnyArray)[]) {\n return _objectMerge(\n {\n next() {\n return true;\n },\n assign({ merge }) {\n return merge();\n },\n },\n target,\n ...sources,\n );\n}\n\n/**\n * 为对象设置默认值。如果目标对象中的属性为 `undefined`,则使用默认对象中的属性值。\n * 支持多个默认对象,优先级从左到右依次降低。\n * 如果目标对象中的属性已经是对象或数组,则递归地设置默认值。\n *\n * @param target - 目标对象或数组。\n * @param defaults - 默认对象或数组。\n * @returns 合并后的对象或数组。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: undefined };\n * const defaults = { a: 4, b: 2, c: 3 };\n * const result = objectDefaults(obj, defaults);\n * console.log(result); // { a: 1, b: 2, c: 3 }\n *\n * const obj2 = { a: 1, b: 2 };\n * const defaults2 = { a: 5, b: 3, c: 4 };\n * const result2 = objectDefaults(obj2, defaults2);\n * console.log(result2); // { a: 1, b: 2, c: 4 }\n *\n * const obj3 = { a: { x: 1 }, b: undefined };\n * const defaults3 = { a: { x: 4, z: 3 }, b: { y: 2 } };\n * const result3 = objectDefaults(obj3, defaults3);\n * console.log(result3); // { a: { x: 1, z: 3 }, b: { y: 2 } }\n * ```\n */\nexport function objectDefaults<T extends AnyObject | AnyArray>(target: T, defaults: T): T {\n return _objectMerge(\n {\n next({ target, key }) {\n return (\n // @ts-expect-error\n target[key] === undefined ||\n // @ts-expect-error\n isObject(target[key]) ||\n // @ts-expect-error\n isArray(target[key])\n );\n },\n assign({ merge }) {\n return merge();\n },\n },\n target,\n defaults,\n ) as T;\n}\n","import type { AnyObject } from '@/types';\n\n/**\n * 从对象中选择指定键的属性,返回一个新的对象。\n *\n * @param object - 要从中选择属性的对象。\n * @param keys - 要选择的键数组。\n * @returns 包含指定键属性的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const result = objectPick(obj, ['a', 'c']);\n * console.log(result); // { a: 1, c: 3 }\n * ```\n */\nexport function objectPick<T extends AnyObject, K extends keyof T>(object: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (key in object) {\n result[key] = object[key];\n }\n }\n return result;\n}\n\n/**\n * 从对象中排除指定键的属性,返回一个新的对象。\n *\n * @param object - 要从中排除属性的对象。\n * @param keys - 要排除的键数组。\n * @returns 排除指定键属性后的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3, d: 4 };\n * const result = objectOmit(obj, ['a', 'd']);\n * console.log(result); // { b: 2, c: 3 }\n * ```\n */\nexport function objectOmit<T extends AnyObject, K extends keyof T>(object: T, keys: K[]): Omit<T, K> {\n const result = {} as Omit<T, K>;\n for (const key in object) {\n if (!keys.includes(key as unknown as K)) {\n // @ts-expect-error\n result[key] = object[key];\n }\n }\n return result;\n}\n\n/**\n * 遍历对象的每个键值对,并对每个键值对执行提供的映射函数,返回一个新的对象。\n *\n * @param object - 要遍历的对象。\n * @param mapper - 对每个键值对执行的映射函数。\n * @returns 返回一个新的对象,其中每个值都是通过映射函数处理后的结果。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3 };\n * const result = objectMap(obj, (val, key) => String(val * 2));\n * console.log(result); // { a: '2', b: '4', c: '6' }\n * ```\n */\nexport function objectMap<T extends AnyObject, V>(\n object: T,\n mapper: (value: T[keyof T], key: keyof T) => V,\n): Record<keyof T, V> {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [\n key,\n mapper(\n // @ts-expect-error\n value,\n key as keyof T,\n ),\n ]),\n ) as Record<keyof T, V>;\n}\n\n/**\n * 根据提供的过滤函数过滤对象的属性,返回一个新对象,只包含满足条件的属性。\n *\n * @param object - 要过滤的对象。\n * @param predicate - 过滤函数,接收值和键作为参数,返回布尔值。\n * @returns 包含满足过滤条件的属性的新对象。\n *\n * @example\n * ```typescript\n * const obj = { a: 1, b: 2, c: 3, d: 4 };\n * const result = objectFilter(obj, (value, key) => value > 2);\n * console.log(result); // { c: 3, d: 4 }\n * ```\n */\nexport function objectFilter<T extends AnyObject>(\n object: T,\n predicate: (value: T[keyof T], key: keyof T) => boolean,\n): Partial<T> {\n return Object.fromEntries(\n Object.entries(object).filter(([key, value]) => predicate(value as T[keyof T], key as keyof T)),\n ) as Partial<T>;\n}\n"],"mappings":"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"}
|