@tldraw/utils 4.3.0-next.82cfddd7ee89 → 4.3.0-next.842fb21476f2
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-cjs/index.d.ts +12 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/control.js +11 -0
- package/dist-cjs/lib/control.js.map +2 -2
- package/dist-cjs/lib/number.js.map +2 -2
- package/dist-cjs/lib/object.js +6 -5
- package/dist-cjs/lib/object.js.map +2 -2
- package/dist-esm/index.d.mts +12 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/control.mjs +11 -0
- package/dist-esm/lib/control.mjs.map +2 -2
- package/dist-esm/lib/number.mjs.map +2 -2
- package/dist-esm/lib/object.mjs +6 -5
- package/dist-esm/lib/object.mjs.map +2 -2
- package/package.json +1 -1
- package/src/lib/control.ts +14 -0
- package/src/lib/number.ts +3 -1
- package/src/lib/object.ts +6 -5
package/dist-cjs/index.d.ts
CHANGED
|
@@ -1067,7 +1067,9 @@ export declare class MediaHelpers {
|
|
|
1067
1067
|
* @example
|
|
1068
1068
|
*
|
|
1069
1069
|
* ```ts
|
|
1070
|
-
* const A = modulate(0, [0, 1], [0, 100])
|
|
1070
|
+
* const A = modulate(0, [0, 1], [0, 100]) // 0
|
|
1071
|
+
* const B = modulate(0.5, [0, 1], [0, 100]) // 50
|
|
1072
|
+
* const C = modulate(1, [0, 1], [0, 100]) // 100
|
|
1071
1073
|
* ```
|
|
1072
1074
|
*
|
|
1073
1075
|
* @param value - The interpolation value.
|
|
@@ -1487,6 +1489,15 @@ export declare const Result: {
|
|
|
1487
1489
|
* @returns An OkResult containing the value
|
|
1488
1490
|
*/
|
|
1489
1491
|
ok<T>(value: T): OkResult<T>;
|
|
1492
|
+
/**
|
|
1493
|
+
* Create a successful result containing an array of values.
|
|
1494
|
+
*
|
|
1495
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
1496
|
+
*
|
|
1497
|
+
* @param results - The array of results to wrap
|
|
1498
|
+
* @returns An OkResult containing the array of values
|
|
1499
|
+
*/
|
|
1500
|
+
all<T>(results: Result<T, any>[]): Result<T[], any>;
|
|
1490
1501
|
};
|
|
1491
1502
|
|
|
1492
1503
|
/* Excluded from this release type: retry */
|
package/dist-cjs/index.js
CHANGED
|
@@ -168,7 +168,7 @@ var import_version2 = require("./lib/version");
|
|
|
168
168
|
var import_warn = require("./lib/warn");
|
|
169
169
|
(0, import_version.registerTldrawLibraryVersion)(
|
|
170
170
|
"@tldraw/utils",
|
|
171
|
-
"4.3.0-next.
|
|
171
|
+
"4.3.0-next.842fb21476f2",
|
|
172
172
|
"cjs"
|
|
173
173
|
);
|
|
174
174
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/lib/control.js
CHANGED
|
@@ -45,6 +45,17 @@ const Result = {
|
|
|
45
45
|
*/
|
|
46
46
|
err(error) {
|
|
47
47
|
return { ok: false, error };
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* Create a successful result containing an array of values.
|
|
51
|
+
*
|
|
52
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
53
|
+
*
|
|
54
|
+
* @param results - The array of results to wrap
|
|
55
|
+
* @returns An OkResult containing the array of values
|
|
56
|
+
*/
|
|
57
|
+
all(results) {
|
|
58
|
+
return results.every((result) => result.ok) ? Result.ok(results.map((result) => result.value)) : Result.err(results.find((result) => !result.ok)?.error);
|
|
48
59
|
}
|
|
49
60
|
};
|
|
50
61
|
function exhaustiveSwitchError(value, property) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/control.ts"],
|
|
4
|
-
"sourcesContent": ["import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAmC;AAqF5B,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrB,GAAM,OAAuB;AAC5B,WAAO,EAAE,IAAI,MAAM,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,OAA0B;AAChC,WAAO,EAAE,IAAI,OAAO,MAAM;AAAA,EAC3B;AACD;AA4BO,SAAS,sBAAsB,OAAc,UAA0B;AAC7E,QAAM,aACL,YAAY,SAAS,OAAO,UAAU,YAAY,YAAY,QAAQ,MAAM,QAAQ,IAAI;AACzF,QAAM,IAAI,MAAM,uBAAuB,UAAU,EAAE;AACpD;AAqBO,MAAM,aAA8D;AAAA,EAC1E,CAAC,OAAO,YAAY;AACnB,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,WAAW,iBAAiB;AAAA,IAC7C;AAAA,EACD;AACD;AAqBO,MAAM,mBAAe,oCAAmB,CAAI,OAAU,YAAqC;AAEjG,MAAI,SAAS,MAAM;AAClB,UAAM,IAAI,MAAM,WAAW,uBAAuB;AAAA,EACnD;AACA,SAAO;AACR,CAAC;AA0BM,SAAS,qBAGd;AACD,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC5C,cAAU;AACV,aAAS;AAAA,EACV,CAAC;AACD,SAAO,OAAO,OAAO,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,EACD,CAAC;AACF;AA2BO,SAAS,MAAM,IAA2B;AAEhD,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;",
|
|
4
|
+
"sourcesContent": ["import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n\n\t/**\n\t * Create a successful result containing an array of values.\n\t *\n\t * If any of the results are errors, the returned result will be an error containing the first error.\n\t *\n\t * @param results - The array of results to wrap\n\t * @returns An OkResult containing the array of values\n\t */\n\tall<T>(results: Result<T, any>[]): Result<T[], any> {\n\t\treturn results.every((result) => result.ok)\n\t\t\t? Result.ok(results.map((result) => result.value))\n\t\t\t: Result.err(results.find((result) => !result.ok)?.error)\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAmC;AAqF5B,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrB,GAAM,OAAuB;AAC5B,WAAO,EAAE,IAAI,MAAM,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,OAA0B;AAChC,WAAO,EAAE,IAAI,OAAO,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAO,SAA6C;AACnD,WAAO,QAAQ,MAAM,CAAC,WAAW,OAAO,EAAE,IACvC,OAAO,GAAG,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,IAC/C,OAAO,IAAI,QAAQ,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,KAAK;AAAA,EAC1D;AACD;AA4BO,SAAS,sBAAsB,OAAc,UAA0B;AAC7E,QAAM,aACL,YAAY,SAAS,OAAO,UAAU,YAAY,YAAY,QAAQ,MAAM,QAAQ,IAAI;AACzF,QAAM,IAAI,MAAM,uBAAuB,UAAU,EAAE;AACpD;AAqBO,MAAM,aAA8D;AAAA,EAC1E,CAAC,OAAO,YAAY;AACnB,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,WAAW,iBAAiB;AAAA,IAC7C;AAAA,EACD;AACD;AAqBO,MAAM,mBAAe,oCAAmB,CAAI,OAAU,YAAqC;AAEjG,MAAI,SAAS,MAAM;AAClB,UAAM,IAAI,MAAM,WAAW,uBAAuB;AAAA,EACnD;AACA,SAAO;AACR,CAAC;AA0BM,SAAS,qBAGd;AACD,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC5C,cAAU;AACV,aAAS;AAAA,EACV,CAAC;AACD,SAAO,OAAO,OAAO,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,EACD,CAAC;AACF;AA2BO,SAAS,MAAM,IAA2B;AAEhD,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/number.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100])\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcO,SAAS,KAAK,GAAW,GAAW,GAAW;AACrD,SAAO,KAAK,IAAI,KAAK;AACtB;AAiBO,SAAS,QAAQ,GAAW,GAAW,GAAW;AACxD,UAAQ,IAAI,MAAM,IAAI;AACvB;AAsBO,SAAS,IAAI,OAAO,IAAI;AAC9B,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AAER,WAAS,OAAO;AACf,UAAM,IAAI,IAAK,KAAK;AACpB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAO,MAAM,KAAM,IAAK,MAAM,OAAQ;AACtC,WAAQ,IAAI,aAAe;AAAA,EAC5B;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,KAAK;AAC1C,SAAK,KAAK,WAAW,CAAC,IAAI;AAC1B,SAAK;AAAA,EACN;AAEA,SAAO;AACR;
|
|
4
|
+
"sourcesContent": ["/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100]) // 0\n * const B = modulate(0.5, [0, 1], [0, 100]) // 50\n * const C = modulate(1, [0, 1], [0, 100]) // 100\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcO,SAAS,KAAK,GAAW,GAAW,GAAW;AACrD,SAAO,KAAK,IAAI,KAAK;AACtB;AAiBO,SAAS,QAAQ,GAAW,GAAW,GAAW;AACxD,UAAQ,IAAI,MAAM,IAAI;AACvB;AAsBO,SAAS,IAAI,OAAO,IAAI;AAC9B,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AAER,WAAS,OAAO;AACf,UAAM,IAAI,IAAK,KAAK;AACpB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAO,MAAM,KAAM,IAAK,MAAM,OAAQ;AACtC,WAAQ,IAAI,aAAe;AAAA,EAC5B;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,KAAK;AAC1C,SAAK,KAAK,WAAW,CAAC,IAAI;AAC1B,SAAK;AAAA,EACN;AAEA,SAAO;AACR;AAmBO,SAAS,SAAS,OAAe,QAAkB,QAAkB,QAAQ,OAAe;AAClG,QAAM,CAAC,SAAS,QAAQ,IAAI;AAC5B,QAAM,CAAC,IAAI,EAAE,IAAI;AACjB,QAAM,SAAS,MAAO,QAAQ,YAAY,WAAW,YAAa,KAAK;AAEvE,SAAO,QACJ,KAAK,KACJ,KAAK,IAAI,KAAK,IAAI,QAAQ,EAAE,GAAG,EAAE,IACjC,KAAK,IAAI,KAAK,IAAI,QAAQ,EAAE,GAAG,EAAE,IAClC;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/lib/object.js
CHANGED
|
@@ -75,7 +75,9 @@ function objectMapFromEntries(entries) {
|
|
|
75
75
|
function filterEntries(object, predicate) {
|
|
76
76
|
const result = {};
|
|
77
77
|
let didChange = false;
|
|
78
|
-
for (const
|
|
78
|
+
for (const key in object) {
|
|
79
|
+
if (!Object.prototype.hasOwnProperty.call(object, key)) continue;
|
|
80
|
+
const value = object[key];
|
|
79
81
|
if (predicate(key, value)) {
|
|
80
82
|
result[key] = value;
|
|
81
83
|
} else {
|
|
@@ -94,11 +96,10 @@ function mapObjectMapValues(object, mapper) {
|
|
|
94
96
|
}
|
|
95
97
|
function areObjectsShallowEqual(obj1, obj2) {
|
|
96
98
|
if (obj1 === obj2) return true;
|
|
97
|
-
const keys1 =
|
|
98
|
-
|
|
99
|
-
if (keys1.size !== keys2.size) return false;
|
|
99
|
+
const keys1 = Object.keys(obj1);
|
|
100
|
+
if (keys1.length !== Object.keys(obj2).length) return false;
|
|
100
101
|
for (const key of keys1) {
|
|
101
|
-
if (!
|
|
102
|
+
if (!hasOwnProperty(obj2, key)) return false;
|
|
102
103
|
if (!Object.is(obj1[key], obj2[key])) return false;
|
|
103
104
|
}
|
|
104
105
|
return true;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/object.ts"],
|
|
4
|
-
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,iBACf,QACqC;AACrC,SAAO,OAAO,QAAQ,MAAM;AAC7B;AAmBO,UAAU,yBAAoD,QAElC;AAClC,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,CAAC,KAAK,OAAO,GAAG,CAAC;AAAA,EACxB;AACD;AAgBO,SAAS,qBACf,SACwB;AACxB,SAAO,OAAO,YAAY,OAAO;AAClC;AAiBO,SAAS,cACf,QACA,WACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,MAAI,YAAY;AAChB,aAAW,CAAC,
|
|
4
|
+
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tconst value = object[key]\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = Object.keys(obj1)\n\tif (keys1.length !== Object.keys(obj2).length) return false\n\tfor (const key of keys1) {\n\t\tif (!hasOwnProperty(obj2, key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,iBACf,QACqC;AACrC,SAAO,OAAO,QAAQ,MAAM;AAC7B;AAmBO,UAAU,yBAAoD,QAElC;AAClC,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,CAAC,KAAK,OAAO,GAAG,CAAC;AAAA,EACxB;AACD;AAgBO,SAAS,qBACf,SACwB;AACxB,SAAO,OAAO,YAAY,OAAO;AAClC;AAiBO,SAAS,cACf,QACA,WACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,MAAI,YAAY;AAChB,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU,KAAK,KAAK,GAAG;AAC1B,aAAO,GAAG,IAAI;AAAA,IACf,OAAO;AACN,kBAAY;AAAA,IACb;AAAA,EACD;AACA,SAAO,YAAa,SAAmC;AACxD;AAiBO,SAAS,mBACf,QACA,QAC6B;AAC7B,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,WAAO,GAAG,IAAI,OAAO,KAAK,OAAO,GAAG,CAAC;AAAA,EACtC;AACA,SAAO;AACR;AAoBO,SAAS,uBAAyC,MAAS,MAAkB;AACnF,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,OAAO,KAAK,IAAI,EAAE,OAAQ,QAAO;AACtD,aAAW,OAAO,OAAO;AACxB,QAAI,CAAC,eAAe,MAAM,GAAG,EAAG,QAAO;AACvC,QAAI,CAAC,OAAO,GAAI,KAAa,GAAG,GAAI,KAAa,GAAG,CAAC,EAAG,QAAO;AAAA,EAChE;AACA,SAAO;AACR;AAqBO,SAAS,QACf,OACA,aACiB;AACjB,QAAM,SAAyB,CAAC;AAChC,aAAW,SAAS,OAAO;AAC1B,UAAM,MAAM,YAAY,KAAK;AAC7B,QAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI,CAAC;AACjC,WAAO,GAAG,EAAE,KAAK,KAAK;AAAA,EACvB;AACA,SAAO;AACR;AAiBO,SAAS,KACf,KACA,MAC0B;AAC1B,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,aAAW,OAAO,MAAM;AACvB,WAAO,OAAO,GAAG;AAAA,EAClB;AACA,SAAO;AACR;AAmBO,SAAS,eAAiC,MAAS,MAAsB;AAC/E,QAAM,SAAsB,CAAC;AAC7B,aAAW,OAAO,MAAM;AACvB,QAAI,CAAC,OAAO,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG;AACrC,aAAO,KAAK,GAAG;AAAA,IAChB;AAAA,EACD;AACA,SAAO;AACR;AAuBO,SAAS,sCACf,MACA,MACA,YAAY,MACF;AACV,aAAO,cAAAA,SAAY,MAAM,MAAM,CAAC,QAAQ,WAAW;AAClD,QAAI,OAAO,WAAW,YAAY,OAAO,WAAW,UAAU;AAC7D,aAAO,KAAK,IAAI,SAAS,MAAM,IAAI;AAAA,IACpC;AACA,WAAO;AAAA,EACR,CAAC;AACF;",
|
|
6
6
|
"names": ["isEqualWith"]
|
|
7
7
|
}
|
package/dist-esm/index.d.mts
CHANGED
|
@@ -1067,7 +1067,9 @@ export declare class MediaHelpers {
|
|
|
1067
1067
|
* @example
|
|
1068
1068
|
*
|
|
1069
1069
|
* ```ts
|
|
1070
|
-
* const A = modulate(0, [0, 1], [0, 100])
|
|
1070
|
+
* const A = modulate(0, [0, 1], [0, 100]) // 0
|
|
1071
|
+
* const B = modulate(0.5, [0, 1], [0, 100]) // 50
|
|
1072
|
+
* const C = modulate(1, [0, 1], [0, 100]) // 100
|
|
1071
1073
|
* ```
|
|
1072
1074
|
*
|
|
1073
1075
|
* @param value - The interpolation value.
|
|
@@ -1487,6 +1489,15 @@ export declare const Result: {
|
|
|
1487
1489
|
* @returns An OkResult containing the value
|
|
1488
1490
|
*/
|
|
1489
1491
|
ok<T>(value: T): OkResult<T>;
|
|
1492
|
+
/**
|
|
1493
|
+
* Create a successful result containing an array of values.
|
|
1494
|
+
*
|
|
1495
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
1496
|
+
*
|
|
1497
|
+
* @param results - The array of results to wrap
|
|
1498
|
+
* @returns An OkResult containing the array of values
|
|
1499
|
+
*/
|
|
1500
|
+
all<T>(results: Result<T, any>[]): Result<T[], any>;
|
|
1490
1501
|
};
|
|
1491
1502
|
|
|
1492
1503
|
/* Excluded from this release type: retry */
|
package/dist-esm/index.mjs
CHANGED
|
@@ -101,7 +101,7 @@ import { registerTldrawLibraryVersion as registerTldrawLibraryVersion2 } from ".
|
|
|
101
101
|
import { warnDeprecatedGetter, warnOnce } from "./lib/warn.mjs";
|
|
102
102
|
registerTldrawLibraryVersion(
|
|
103
103
|
"@tldraw/utils",
|
|
104
|
-
"4.3.0-next.
|
|
104
|
+
"4.3.0-next.842fb21476f2",
|
|
105
105
|
"esm"
|
|
106
106
|
);
|
|
107
107
|
export {
|
package/dist-esm/lib/control.mjs
CHANGED
|
@@ -17,6 +17,17 @@ const Result = {
|
|
|
17
17
|
*/
|
|
18
18
|
err(error) {
|
|
19
19
|
return { ok: false, error };
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Create a successful result containing an array of values.
|
|
23
|
+
*
|
|
24
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
25
|
+
*
|
|
26
|
+
* @param results - The array of results to wrap
|
|
27
|
+
* @returns An OkResult containing the array of values
|
|
28
|
+
*/
|
|
29
|
+
all(results) {
|
|
30
|
+
return results.every((result) => result.ok) ? Result.ok(results.map((result) => result.value)) : Result.err(results.find((result) => !result.ok)?.error);
|
|
20
31
|
}
|
|
21
32
|
};
|
|
22
33
|
function exhaustiveSwitchError(value, property) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/control.ts"],
|
|
4
|
-
"sourcesContent": ["import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,0BAA0B;AAqF5B,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrB,GAAM,OAAuB;AAC5B,WAAO,EAAE,IAAI,MAAM,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,OAA0B;AAChC,WAAO,EAAE,IAAI,OAAO,MAAM;AAAA,EAC3B;AACD;AA4BO,SAAS,sBAAsB,OAAc,UAA0B;AAC7E,QAAM,aACL,YAAY,SAAS,OAAO,UAAU,YAAY,YAAY,QAAQ,MAAM,QAAQ,IAAI;AACzF,QAAM,IAAI,MAAM,uBAAuB,UAAU,EAAE;AACpD;AAqBO,MAAM,SAA8D;AAAA,EAC1E,CAAC,OAAO,YAAY;AACnB,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,WAAW,iBAAiB;AAAA,IAC7C;AAAA,EACD;AACD;AAqBO,MAAM,eAAe,mBAAmB,CAAI,OAAU,YAAqC;AAEjG,MAAI,SAAS,MAAM;AAClB,UAAM,IAAI,MAAM,WAAW,uBAAuB;AAAA,EACnD;AACA,SAAO;AACR,CAAC;AA0BM,SAAS,qBAGd;AACD,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC5C,cAAU;AACV,aAAS;AAAA,EACV,CAAC;AACD,SAAO,OAAO,OAAO,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,EACD,CAAC;AACF;AA2BO,SAAS,MAAM,IAA2B;AAEhD,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;",
|
|
4
|
+
"sourcesContent": ["import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n\n\t/**\n\t * Create a successful result containing an array of values.\n\t *\n\t * If any of the results are errors, the returned result will be an error containing the first error.\n\t *\n\t * @param results - The array of results to wrap\n\t * @returns An OkResult containing the array of values\n\t */\n\tall<T>(results: Result<T, any>[]): Result<T[], any> {\n\t\treturn results.every((result) => result.ok)\n\t\t\t? Result.ok(results.map((result) => result.value))\n\t\t\t: Result.err(results.find((result) => !result.ok)?.error)\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,0BAA0B;AAqF5B,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrB,GAAM,OAAuB;AAC5B,WAAO,EAAE,IAAI,MAAM,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,OAA0B;AAChC,WAAO,EAAE,IAAI,OAAO,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAO,SAA6C;AACnD,WAAO,QAAQ,MAAM,CAAC,WAAW,OAAO,EAAE,IACvC,OAAO,GAAG,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,IAC/C,OAAO,IAAI,QAAQ,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,KAAK;AAAA,EAC1D;AACD;AA4BO,SAAS,sBAAsB,OAAc,UAA0B;AAC7E,QAAM,aACL,YAAY,SAAS,OAAO,UAAU,YAAY,YAAY,QAAQ,MAAM,QAAQ,IAAI;AACzF,QAAM,IAAI,MAAM,uBAAuB,UAAU,EAAE;AACpD;AAqBO,MAAM,SAA8D;AAAA,EAC1E,CAAC,OAAO,YAAY;AACnB,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,WAAW,iBAAiB;AAAA,IAC7C;AAAA,EACD;AACD;AAqBO,MAAM,eAAe,mBAAmB,CAAI,OAAU,YAAqC;AAEjG,MAAI,SAAS,MAAM;AAClB,UAAM,IAAI,MAAM,WAAW,uBAAuB;AAAA,EACnD;AACA,SAAO;AACR,CAAC;AA0BM,SAAS,qBAGd;AACD,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC5C,cAAU;AACV,aAAS;AAAA,EACV,CAAC;AACD,SAAO,OAAO,OAAO,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,EACD,CAAC;AACF;AA2BO,SAAS,MAAM,IAA2B;AAEhD,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/number.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100])\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n"],
|
|
5
|
-
"mappings": "AAcO,SAAS,KAAK,GAAW,GAAW,GAAW;AACrD,SAAO,KAAK,IAAI,KAAK;AACtB;AAiBO,SAAS,QAAQ,GAAW,GAAW,GAAW;AACxD,UAAQ,IAAI,MAAM,IAAI;AACvB;AAsBO,SAAS,IAAI,OAAO,IAAI;AAC9B,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AAER,WAAS,OAAO;AACf,UAAM,IAAI,IAAK,KAAK;AACpB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAO,MAAM,KAAM,IAAK,MAAM,OAAQ;AACtC,WAAQ,IAAI,aAAe;AAAA,EAC5B;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,KAAK;AAC1C,SAAK,KAAK,WAAW,CAAC,IAAI;AAC1B,SAAK;AAAA,EACN;AAEA,SAAO;AACR;
|
|
4
|
+
"sourcesContent": ["/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100]) // 0\n * const B = modulate(0.5, [0, 1], [0, 100]) // 50\n * const C = modulate(1, [0, 1], [0, 100]) // 100\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n"],
|
|
5
|
+
"mappings": "AAcO,SAAS,KAAK,GAAW,GAAW,GAAW;AACrD,SAAO,KAAK,IAAI,KAAK;AACtB;AAiBO,SAAS,QAAQ,GAAW,GAAW,GAAW;AACxD,UAAQ,IAAI,MAAM,IAAI;AACvB;AAsBO,SAAS,IAAI,OAAO,IAAI;AAC9B,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AAER,WAAS,OAAO;AACf,UAAM,IAAI,IAAK,KAAK;AACpB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAO,MAAM,KAAM,IAAK,MAAM,OAAQ;AACtC,WAAQ,IAAI,aAAe;AAAA,EAC5B;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,KAAK;AAC1C,SAAK,KAAK,WAAW,CAAC,IAAI;AAC1B,SAAK;AAAA,EACN;AAEA,SAAO;AACR;AAmBO,SAAS,SAAS,OAAe,QAAkB,QAAkB,QAAQ,OAAe;AAClG,QAAM,CAAC,SAAS,QAAQ,IAAI;AAC5B,QAAM,CAAC,IAAI,EAAE,IAAI;AACjB,QAAM,SAAS,MAAO,QAAQ,YAAY,WAAW,YAAa,KAAK;AAEvE,SAAO,QACJ,KAAK,KACJ,KAAK,IAAI,KAAK,IAAI,QAAQ,EAAE,GAAG,EAAE,IACjC,KAAK,IAAI,KAAK,IAAI,QAAQ,EAAE,GAAG,EAAE,IAClC;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/lib/object.mjs
CHANGED
|
@@ -29,7 +29,9 @@ function objectMapFromEntries(entries) {
|
|
|
29
29
|
function filterEntries(object, predicate) {
|
|
30
30
|
const result = {};
|
|
31
31
|
let didChange = false;
|
|
32
|
-
for (const
|
|
32
|
+
for (const key in object) {
|
|
33
|
+
if (!Object.prototype.hasOwnProperty.call(object, key)) continue;
|
|
34
|
+
const value = object[key];
|
|
33
35
|
if (predicate(key, value)) {
|
|
34
36
|
result[key] = value;
|
|
35
37
|
} else {
|
|
@@ -48,11 +50,10 @@ function mapObjectMapValues(object, mapper) {
|
|
|
48
50
|
}
|
|
49
51
|
function areObjectsShallowEqual(obj1, obj2) {
|
|
50
52
|
if (obj1 === obj2) return true;
|
|
51
|
-
const keys1 =
|
|
52
|
-
|
|
53
|
-
if (keys1.size !== keys2.size) return false;
|
|
53
|
+
const keys1 = Object.keys(obj1);
|
|
54
|
+
if (keys1.length !== Object.keys(obj2).length) return false;
|
|
54
55
|
for (const key of keys1) {
|
|
55
|
-
if (!
|
|
56
|
+
if (!hasOwnProperty(obj2, key)) return false;
|
|
56
57
|
if (!Object.is(obj1[key], obj2[key])) return false;
|
|
57
58
|
}
|
|
58
59
|
return true;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/object.ts"],
|
|
4
|
-
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const [key, value] of objectMapEntries(object)) {\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = new Set(Object.keys(obj1))\n\tconst keys2 = new Set(Object.keys(obj2))\n\tif (keys1.size !== keys2.size) return false\n\tfor (const key of keys1) {\n\t\tif (!keys2.has(key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,iBAAiB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,iBACf,QACqC;AACrC,SAAO,OAAO,QAAQ,MAAM;AAC7B;AAmBO,UAAU,yBAAoD,QAElC;AAClC,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,CAAC,KAAK,OAAO,GAAG,CAAC;AAAA,EACxB;AACD;AAgBO,SAAS,qBACf,SACwB;AACxB,SAAO,OAAO,YAAY,OAAO;AAClC;AAiBO,SAAS,cACf,QACA,WACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,MAAI,YAAY;AAChB,aAAW,CAAC,
|
|
4
|
+
"sourcesContent": ["import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tconst value = object[key]\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = Object.keys(obj1)\n\tif (keys1.length !== Object.keys(obj2).length) return false\n\tfor (const key of keys1) {\n\t\tif (!hasOwnProperty(obj2, key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,iBAAiB;AAmBjB,SAAS,eAAe,KAAa,KAAsB;AACjE,SAAO,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG;AACrD;AA2BO,SAAS,eAAe,KAAa,KAAsB;AACjE,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,SAAO,IAAI,GAAG;AACf;AAgBO,SAAS,cAAkC,QAEnC;AACd,SAAO,OAAO,KAAK,MAAM;AAC1B;AAgBO,SAAS,gBAA2C,QAE1C;AAChB,SAAO,OAAO,OAAO,MAAM;AAC5B;AAgBO,SAAS,iBACf,QACqC;AACrC,SAAO,OAAO,QAAQ,MAAM;AAC7B;AAmBO,UAAU,yBAAoD,QAElC;AAClC,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,CAAC,KAAK,OAAO,GAAG,CAAC;AAAA,EACxB;AACD;AAgBO,SAAS,qBACf,SACwB;AACxB,SAAO,OAAO,YAAY,OAAO;AAClC;AAiBO,SAAS,cACf,QACA,WACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,MAAI,YAAY;AAChB,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU,KAAK,KAAK,GAAG;AAC1B,aAAO,GAAG,IAAI;AAAA,IACf,OAAO;AACN,kBAAY;AAAA,IACb;AAAA,EACD;AACA,SAAO,YAAa,SAAmC;AACxD;AAiBO,SAAS,mBACf,QACA,QAC6B;AAC7B,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,QAAQ;AACzB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,EAAG;AACxD,WAAO,GAAG,IAAI,OAAO,KAAK,OAAO,GAAG,CAAC;AAAA,EACtC;AACA,SAAO;AACR;AAoBO,SAAS,uBAAyC,MAAS,MAAkB;AACnF,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,OAAO,KAAK,IAAI,EAAE,OAAQ,QAAO;AACtD,aAAW,OAAO,OAAO;AACxB,QAAI,CAAC,eAAe,MAAM,GAAG,EAAG,QAAO;AACvC,QAAI,CAAC,OAAO,GAAI,KAAa,GAAG,GAAI,KAAa,GAAG,CAAC,EAAG,QAAO;AAAA,EAChE;AACA,SAAO;AACR;AAqBO,SAAS,QACf,OACA,aACiB;AACjB,QAAM,SAAyB,CAAC;AAChC,aAAW,SAAS,OAAO;AAC1B,UAAM,MAAM,YAAY,KAAK;AAC7B,QAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI,CAAC;AACjC,WAAO,GAAG,EAAE,KAAK,KAAK;AAAA,EACvB;AACA,SAAO;AACR;AAiBO,SAAS,KACf,KACA,MAC0B;AAC1B,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,aAAW,OAAO,MAAM;AACvB,WAAO,OAAO,GAAG;AAAA,EAClB;AACA,SAAO;AACR;AAmBO,SAAS,eAAiC,MAAS,MAAsB;AAC/E,QAAM,SAAsB,CAAC;AAC7B,aAAW,OAAO,MAAM;AACvB,QAAI,CAAC,OAAO,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG;AACrC,aAAO,KAAK,GAAG;AAAA,IAChB;AAAA,EACD;AACA,SAAO;AACR;AAuBO,SAAS,sCACf,MACA,MACA,YAAY,MACF;AACV,SAAO,YAAY,MAAM,MAAM,CAAC,QAAQ,WAAW;AAClD,QAAI,OAAO,WAAW,YAAY,OAAO,WAAW,UAAU;AAC7D,aAAO,KAAK,IAAI,SAAS,MAAM,IAAI;AAAA,IACpC;AACA,WAAO;AAAA,EACR,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
package/src/lib/control.ts
CHANGED
|
@@ -102,6 +102,20 @@ export const Result = {
|
|
|
102
102
|
err<E>(error: E): ErrorResult<E> {
|
|
103
103
|
return { ok: false, error }
|
|
104
104
|
},
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Create a successful result containing an array of values.
|
|
108
|
+
*
|
|
109
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
110
|
+
*
|
|
111
|
+
* @param results - The array of results to wrap
|
|
112
|
+
* @returns An OkResult containing the array of values
|
|
113
|
+
*/
|
|
114
|
+
all<T>(results: Result<T, any>[]): Result<T[], any> {
|
|
115
|
+
return results.every((result) => result.ok)
|
|
116
|
+
? Result.ok(results.map((result) => result.value))
|
|
117
|
+
: Result.err(results.find((result) => !result.ok)?.error)
|
|
118
|
+
},
|
|
105
119
|
}
|
|
106
120
|
|
|
107
121
|
/**
|
package/src/lib/number.ts
CHANGED
|
@@ -84,7 +84,9 @@ export function rng(seed = '') {
|
|
|
84
84
|
* @example
|
|
85
85
|
*
|
|
86
86
|
* ```ts
|
|
87
|
-
* const A = modulate(0, [0, 1], [0, 100])
|
|
87
|
+
* const A = modulate(0, [0, 1], [0, 100]) // 0
|
|
88
|
+
* const B = modulate(0.5, [0, 1], [0, 100]) // 50
|
|
89
|
+
* const C = modulate(1, [0, 1], [0, 100]) // 100
|
|
88
90
|
* ```
|
|
89
91
|
*
|
|
90
92
|
* @param value - The interpolation value.
|
package/src/lib/object.ts
CHANGED
|
@@ -181,7 +181,9 @@ export function filterEntries<Key extends string, Value>(
|
|
|
181
181
|
): { [K in Key]: Value } {
|
|
182
182
|
const result: { [K in Key]?: Value } = {}
|
|
183
183
|
let didChange = false
|
|
184
|
-
for (const
|
|
184
|
+
for (const key in object) {
|
|
185
|
+
if (!Object.prototype.hasOwnProperty.call(object, key)) continue
|
|
186
|
+
const value = object[key]
|
|
185
187
|
if (predicate(key, value)) {
|
|
186
188
|
result[key] = value
|
|
187
189
|
} else {
|
|
@@ -238,11 +240,10 @@ export function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(
|
|
|
238
240
|
*/
|
|
239
241
|
export function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {
|
|
240
242
|
if (obj1 === obj2) return true
|
|
241
|
-
const keys1 =
|
|
242
|
-
|
|
243
|
-
if (keys1.size !== keys2.size) return false
|
|
243
|
+
const keys1 = Object.keys(obj1)
|
|
244
|
+
if (keys1.length !== Object.keys(obj2).length) return false
|
|
244
245
|
for (const key of keys1) {
|
|
245
|
-
if (!
|
|
246
|
+
if (!hasOwnProperty(obj2, key)) return false
|
|
246
247
|
if (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false
|
|
247
248
|
}
|
|
248
249
|
return true
|