@radham/utils 0.1.0
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/CHANGELOG.md +16 -0
- package/LICENSE +28 -0
- package/README.md +152 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +48 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/package.json +48 -0
- package/dist/types/attempt.d.ts +14 -0
- package/dist/types/attempt.d.ts.map +1 -0
- package/dist/types/capitalize.d.ts +13 -0
- package/dist/types/capitalize.d.ts.map +1 -0
- package/dist/types/compose.d.ts +16 -0
- package/dist/types/compose.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/is-number-like.d.ts +36 -0
- package/dist/types/is-number-like.d.ts.map +1 -0
- package/dist/types/is-number.d.ts +22 -0
- package/dist/types/is-number.d.ts.map +1 -0
- package/dist/types/is-plain-object.d.ts +18 -0
- package/dist/types/is-plain-object.d.ts.map +1 -0
- package/dist/types/is-string.d.ts +14 -0
- package/dist/types/is-string.d.ts.map +1 -0
- package/dist/types/omit.d.ts +16 -0
- package/dist/types/omit.d.ts.map +1 -0
- package/dist/types/range.d.ts +21 -0
- package/dist/types/range.d.ts.map +1 -0
- package/dist/types/to-string.d.ts +14 -0
- package/dist/types/to-string.d.ts.map +1 -0
- package/dist/types/unique.d.ts +13 -0
- package/dist/types/unique.d.ts.map +1 -0
- package/package.json +72 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Changelog
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
All notable changes to this project will be documented in this file.
|
|
5
|
+
|
|
6
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
7
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
|
+
|
|
9
|
+
[0.1.0] - 2026-02-08
|
|
10
|
+
--------------------
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release.
|
|
15
|
+
|
|
16
|
+
[0.1.0]: https://github.com/jbenner-radham/node-utils/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, James Benner
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
@radham/utils
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
A small bespoke utility library.
|
|
5
|
+
|
|
6
|
+
Install
|
|
7
|
+
-------
|
|
8
|
+
|
|
9
|
+
...
|
|
10
|
+
|
|
11
|
+
Usage
|
|
12
|
+
-----
|
|
13
|
+
|
|
14
|
+
### attempt
|
|
15
|
+
|
|
16
|
+
Executes a function and returns its result, or `undefined` if it throws.
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { attempt } from '@radham/utils';
|
|
20
|
+
|
|
21
|
+
attempt(() => JSON.parse('{"a":1}')); // { a: 1 }
|
|
22
|
+
attempt(() => JSON.parse('invalid')); // undefined
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### capitalize
|
|
26
|
+
|
|
27
|
+
Capitalizes the first character of a string.
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { capitalize } from '@radham/utils';
|
|
31
|
+
|
|
32
|
+
capitalize('hello'); // 'Hello'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### compose
|
|
36
|
+
|
|
37
|
+
Composes multiple functions into a single function that applies them from left to right.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { compose } from '@radham/utils';
|
|
41
|
+
|
|
42
|
+
const addOne = (value: number) => value + 1;
|
|
43
|
+
const double = (value: number) => value * 2;
|
|
44
|
+
|
|
45
|
+
compose(addOne, double)(3); // 8
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### isNumber
|
|
49
|
+
|
|
50
|
+
Checks whether the given value is a number.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { isNumber } from '@radham/utils';
|
|
54
|
+
|
|
55
|
+
isNumber(42); // true
|
|
56
|
+
isNumber('42'); // false
|
|
57
|
+
isNumber(NaN); // true
|
|
58
|
+
isNumber(NaN, { finite: true }); // false
|
|
59
|
+
isNumber(Infinity, { finite: true }); // false
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### isNumberLike
|
|
63
|
+
|
|
64
|
+
Checks whether the given value is a number or can be coerced to one.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { isNumberLike } from '@radham/utils';
|
|
68
|
+
|
|
69
|
+
isNumberLike(42); // true
|
|
70
|
+
isNumberLike('42'); // true
|
|
71
|
+
isNumberLike('3.14'); // true
|
|
72
|
+
isNumberLike('NaN'); // true
|
|
73
|
+
isNumberLike('NaN', { finite: true }); // false
|
|
74
|
+
isNumberLike('Infinity', { finite: true }); // false
|
|
75
|
+
isNumberLike('abc'); // false
|
|
76
|
+
isNumberLike(null); // false
|
|
77
|
+
isNumberLike(1n); // false
|
|
78
|
+
isNumberLike(1n, { bigint: true }); // true
|
|
79
|
+
isNumberLike('1n', { bigint: true }); // true
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### isPlainObject
|
|
83
|
+
|
|
84
|
+
Checks whether the given value is a plain object.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { isPlainObject } from '@radham/utils';
|
|
88
|
+
|
|
89
|
+
isPlainObject({ a: 1 }); // true
|
|
90
|
+
isPlainObject([1, 2, 3]); // false
|
|
91
|
+
isPlainObject(null); // false
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### isString
|
|
95
|
+
|
|
96
|
+
Checks whether the given value is a string.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { isString } from '@radham/utils';
|
|
100
|
+
|
|
101
|
+
isString('hello'); // true
|
|
102
|
+
isString(42); // false
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### omit
|
|
106
|
+
|
|
107
|
+
Creates a new object with the specified keys omitted.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { omit } from '@radham/utils';
|
|
111
|
+
|
|
112
|
+
omit({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { b: 2 }
|
|
113
|
+
omit({ a: 1, b: 2 }, 'a'); // { b: 2 }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### range
|
|
117
|
+
|
|
118
|
+
Creates an array of numbers from `start` (inclusive) to `end` (exclusive).
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { range } from '@radham/utils';
|
|
122
|
+
|
|
123
|
+
range(4); // [0, 1, 2, 3]
|
|
124
|
+
range(2, 5); // [2, 3, 4]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### toString
|
|
128
|
+
|
|
129
|
+
Converts a value to its string representation.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { toString } from '@radham/utils';
|
|
133
|
+
|
|
134
|
+
toString(42); // '42'
|
|
135
|
+
toString(null); // 'null'
|
|
136
|
+
toString(undefined); // 'undefined'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### unique
|
|
140
|
+
|
|
141
|
+
Returns a new array with duplicate values removed.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { unique } from '@radham/utils';
|
|
145
|
+
|
|
146
|
+
unique([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
License
|
|
150
|
+
-------
|
|
151
|
+
|
|
152
|
+
The BSD 3-Clause License. See the [license file](LICENSE) for details.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var a=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var k=(e,t)=>{for(var r in t)a(e,r,{get:t[r],enumerable:!0})},S=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of T(t))!w.call(e,i)&&i!==r&&a(e,i,{get:()=>t[i],enumerable:!(n=N(t,i))||n.enumerable});return e};var O=e=>S(a({},"__esModule",{value:!0}),e);var h={};k(h,{attempt:()=>o,capitalize:()=>s,compose:()=>l,isNumber:()=>u,isNumberLike:()=>p,isPlainObject:()=>m,isString:()=>c,omit:()=>b,range:()=>d,toString:()=>g,unique:()=>y});module.exports=O(h);function o(e){try{return e()}catch{}}function s(e){return e.charAt(0).toUpperCase()+e.slice(1)}function l(...e){return t=>e.reduce((r,n)=>n(r),t)}function u(e,t){return typeof e=="number"&&(!t?.finite||Number.isFinite(e))}function p(e,t){if(typeof e=="bigint")return!!t?.bigint;if(typeof e=="string"&&t?.bigint)return!!(o(()=>BigInt(e))??!1);if(typeof e=="string"&&["-Infinity","Infinity","NaN"].includes(e))return!t?.finite;let n=["",!1,null],i=[!0];if(n.includes(e)||i.includes(e))return!1;let f=Number(e);return typeof e!="number"&&Number.isNaN(f)?!1:u(f,t)}function m(e){if(typeof e!="object"||e===null)return!1;let t=Object.getPrototypeOf(e);return t!==null&&t!==Object.prototype?!1:!Object.hasOwn(e,Symbol.toStringTag)}function c(e){return typeof e=="string"}function b(e,t){let r=Array.isArray(t)?t:[t];return Object.fromEntries(Object.entries(e).filter(([n])=>!r.includes(n)))}function d(e,t){let r=t===void 0?0:e,n=t??e;if(!Number.isInteger(r)||!Number.isInteger(n))throw new TypeError(`Expected integer arguments, received start (${r}), and end (${n}).`);let i=n-r;if(i<0)throw new RangeError(`Invalid range: start (${r}) must not be greater than end (${n}).`);return Array.from({length:i},(f,x)=>r+x)}function g(e){return e?.toString?.()??String(e)}function y(e){return e.filter((t,r)=>e.indexOf(t)===r)}
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts", "../../src/attempt.ts", "../../src/capitalize.ts", "../../src/compose.ts", "../../src/is-number.ts", "../../src/is-number-like.ts", "../../src/is-plain-object.ts", "../../src/is-string.ts", "../../src/omit.ts", "../../src/range.ts", "../../src/to-string.ts", "../../src/unique.ts"],
|
|
4
|
+
"sourcesContent": ["export { default as attempt } from './attempt.js';\nexport { default as capitalize } from './capitalize.js';\nexport { default as compose } from './compose.js';\nexport { default as isNumber } from './is-number.js';\nexport { default as isNumberLike } from './is-number-like.js';\nexport { default as isPlainObject } from './is-plain-object.js';\nexport { default as isString } from './is-string.js';\nexport { default as omit } from './omit.js';\nexport { default as range } from './range.js';\nexport { default as toString } from './to-string.js';\nexport { default as unique } from './unique.js';\n", "/**\n * Executes a function and returns its result, or `undefined` if it throws.\n *\n * @param callback - The function to execute.\n * @returns The return value of `callback`, or `undefined` if an error is thrown.\n *\n * @example\n * ```typescript\n * attempt(() => JSON.parse('{\"a\":1}')); // { a: 1 }\n * attempt(() => JSON.parse('invalid')); // undefined\n * ```\n */\nexport default function attempt<T>(callback: () => T): T | undefined {\n try {\n return callback();\n } catch { /* Do nothing. */ }\n}\n", "/**\n * Capitalizes the first character of a string.\n *\n * @param value - The string to capitalize.\n * @returns A new string with the first character in uppercase.\n *\n * @example\n * ```typescript\n * capitalize('hello'); // 'Hello'\n * ```\n */\nexport default function capitalize<T extends string>(value: T): Capitalize<T> {\n return (value.charAt(0).toUpperCase() + value.slice(1)) as Capitalize<T>;\n}\n", "/**\n * Composes multiple functions into a single function that applies them from left to right.\n *\n * @param functions - The functions to compose, each taking and returning the same type.\n * @returns A function that pipes a value through each function in order.\n *\n * @example\n * ```typescript\n * const addOne = (value: number) => value + 1;\n * const double = (value: number) => value * 2;\n *\n * compose(addOne, double)(3); // 8\n * ```\n */\nexport default function compose<T>(...functions: Array<(value: T) => T>): (value: T) => T {\n return (value: T) => functions.reduce((accumulator, fn) => fn(accumulator), value);\n}\n", "/**\n * Checks whether the given value is a number.\n *\n * @param value - The value to check.\n * @param options - Optional configuration.\n * @param options.finite - When `true`, only finite numbers are considered valid (`NaN` and\n * `Infinity` return `false`).\n * @returns `true` if `value` is a number, `false` otherwise.\n *\n * @example\n * ```typescript\n * isNumber(42); // true\n * isNumber('42'); // false\n * isNumber(NaN); // true\n * isNumber(NaN, { finite: true }); // false\n * isNumber(Infinity, { finite: true }); // false\n * ```\n */\nexport default function isNumber(\n value: unknown, options?: { finite?: boolean }\n): value is number {\n return typeof value === 'number' && (!options?.finite || Number.isFinite(value));\n}\n", "import attempt from './attempt.js';\nimport isNumber from './is-number.js';\n\n/**\n * Checks whether the given value is a number or can be coerced to one.\n *\n * @remarks\n * This function only considers actual numbers and strings that represent numbers as\n * number-like. Even though the values `''`, `false`, and `null` convert to `0`, and\n * `true` converts to `1`, none of these are considered number-like by this function.\n *\n * @param value - The value to check.\n * @param options - Optional configuration.\n * @param options.bigint - When `true`, bigints and strings that can be converted to\n * bigints are considered valid.\n * @param options.finite - When `true`, only finite numbers are considered valid (`NaN`,\n * `Infinity`, and their string equivalents return `false`).\n * @returns `true` if `value` is number-like, `false` otherwise.\n *\n * @example\n * ```typescript\n * isNumberLike(42); // true\n * isNumberLike('42'); // true\n * isNumberLike('3.14'); // true\n * isNumberLike('NaN'); // true\n * isNumberLike('NaN', { finite: true }); // false\n * isNumberLike('Infinity', { finite: true }); // false\n * isNumberLike('abc'); // false\n * isNumberLike(null); // false\n * isNumberLike(1n); // false\n * isNumberLike(1n, { bigint: true }); // true\n * isNumberLike('1n', { bigint: true }); // true\n * ```\n */\nexport default function isNumberLike(\n value: unknown, options?: { bigint?: boolean; finite?: boolean }\n): value is number {\n // `Number()` will coerce bigints to numbers, so we need to make this check.\n if (typeof value === 'bigint') {\n return Boolean(options?.bigint);\n }\n\n if (typeof value === 'string' && options?.bigint) {\n return Boolean(attempt(() => BigInt(value)) ?? false);\n }\n\n const infiniteNumberStrings = ['-Infinity', 'Infinity', 'NaN'];\n\n if (typeof value === 'string' && infiniteNumberStrings.includes(value)) {\n return !options?.finite;\n }\n\n // These values are converted to `0` by `Number()`.\n const falsyNumberValues = ['', false, null];\n\n // These values are converted to `1` by `Number()`.\n const truthyNumberValues = [true];\n\n if (\n falsyNumberValues.includes(value as boolean | null | string) ||\n truthyNumberValues.includes(value as boolean)\n ) {\n return false;\n }\n\n const numberValue = Number(value);\n\n if (typeof value !== 'number' && Number.isNaN(numberValue)) {\n return false;\n }\n\n return isNumber(numberValue, options);\n}\n", "/**\n * Checks whether the given value is a plain object.\n *\n * @remarks\n * A plain object is one created by the `Object` constructor, a `null` prototype, or an object\n * literal.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is a plain object, `false` otherwise.\n *\n * @example\n * ```typescript\n * isPlainObject({ a: 1 }); // true\n * isPlainObject([1, 2]); // false\n * ```\n */\nexport default function isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value) as unknown;\n\n if (prototype !== null && prototype !== Object.prototype) {\n return false;\n }\n\n // This is needed for `Atomics`, `Intl`, `JSON`, `Math`, and `Reflect`.\n return !Object.hasOwn(value, Symbol.toStringTag);\n}\n", "/**\n * Checks whether the given value is a string.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is a string, `false` otherwise.\n *\n * @example\n * ```typescript\n * isString('hello'); // true\n * isString(42); // false\n * ```\n */\nexport default function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n", "/**\n * Creates a new object with the specified keys omitted.\n *\n * @param object - The source object to omit keys from.\n * @param omitted - A key or array of keys to exclude from the result.\n * @returns A new object containing all entries from `object` except those with keys in `omitted`.\n *\n * @example\n * ```typescript\n * omit({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { b: 2 }\n * ```\n */\nexport default function omit(\n object: Record<PropertyKey, unknown>, omitted: PropertyKey | PropertyKey[]\n) {\n const omittedKeys = Array.isArray(omitted) ? omitted : [omitted];\n\n return Object.fromEntries(\n Object.entries(object).filter(([key]) => !omittedKeys.includes(key))\n );\n}\n", "/**\n * Creates an array of integers from `start` (inclusive) to `end` (exclusive).\n *\n * @remarks\n * When called with a single argument, it generates a range from `0` to that value.\n *\n * @param startOrEnd - The start of the range if `maybeEnd` is provided, otherwise the end.\n * @param maybeEnd - The end of the range (exclusive). Must be greater than or equal to `start`.\n * @returns An array of sequential integers.\n *\n * @throws {@link TypeError} If either argument is not a finite integer.\n * @throws {@link RangeError} If `start` is greater than `end`.\n *\n * @example\n * ```typescript\n * range(4); // [0, 1, 2, 3]\n * range(2, 5); // [2, 3, 4]\n * ```\n */\nexport default function range(startOrEnd: number, maybeEnd?: number): number[] {\n const start = maybeEnd === undefined ? 0 : startOrEnd;\n const end = maybeEnd ?? startOrEnd;\n\n if (!Number.isInteger(start) || !Number.isInteger(end)) {\n throw new TypeError(`Expected integer arguments, received start (${start}), and end (${end}).`);\n }\n\n const length = end - start;\n\n if (length < 0) {\n throw new RangeError(`Invalid range: start (${start}) must not be greater than end (${end}).`);\n }\n\n return Array.from({ length }, (_, index) => start + index);\n}\n", "/**\n * Converts a value to its string representation.\n *\n * @param value - The value to convert.\n * @returns The string representation of `value`.\n *\n * @example\n * ```typescript\n * toString(42); // '42'\n * toString(null); // 'null'\n * ```\n */\nexport default function toString(value: unknown): string {\n return value?.toString?.() ?? String(value);\n}\n", "/**\n * Returns a new array with duplicate values removed.\n *\n * @param array - The array to deduplicate.\n * @returns A new array containing only the first occurrence of each value.\n *\n * @example\n * ```typescript\n * unique([1, 2, 2, 3, 1]); // [1, 2, 3]\n * ```\n */\nexport default function unique<T>(array: T[]): T[] {\n // NOTE: This benchmarks significantly better than `return [...new Set(array)]`.\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,EAAA,eAAAC,EAAA,YAAAC,EAAA,aAAAC,EAAA,iBAAAC,EAAA,kBAAAC,EAAA,aAAAC,EAAA,SAAAC,EAAA,UAAAC,EAAA,aAAAC,EAAA,WAAAC,IAAA,eAAAC,EAAAb,GCYe,SAARc,EAA4BC,EAAkC,CACnE,GAAI,CACF,OAAOA,EAAS,CAClB,MAAQ,CAAoB,CAC9B,CCLe,SAARC,EAA8CC,EAAyB,CAC5E,OAAQA,EAAM,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAM,MAAM,CAAC,CACvD,CCCe,SAARC,KAA+BC,EAAoD,CACxF,OAAQC,GAAaD,EAAU,OAAO,CAACE,EAAaC,IAAOA,EAAGD,CAAW,EAAGD,CAAK,CACnF,CCEe,SAARG,EACLC,EAAgBC,EACC,CACjB,OAAO,OAAOD,GAAU,WAAa,CAACC,GAAS,QAAU,OAAO,SAASD,CAAK,EAChF,CCYe,SAARE,EACLC,EAAgBC,EACC,CAEjB,GAAI,OAAOD,GAAU,SACnB,MAAO,EAAQC,GAAS,OAG1B,GAAI,OAAOD,GAAU,UAAYC,GAAS,OACxC,MAAO,GAAQC,EAAQ,IAAM,OAAOF,CAAK,CAAC,GAAK,IAKjD,GAAI,OAAOA,GAAU,UAFS,CAAC,YAAa,WAAY,KAAK,EAEN,SAASA,CAAK,EACnE,MAAO,CAACC,GAAS,OAInB,IAAME,EAAoB,CAAC,GAAI,GAAO,IAAI,EAGpCC,EAAqB,CAAC,EAAI,EAEhC,GACED,EAAkB,SAASH,CAAgC,GAC3DI,EAAmB,SAASJ,CAAgB,EAE5C,MAAO,GAGT,IAAMK,EAAc,OAAOL,CAAK,EAEhC,OAAI,OAAOA,GAAU,UAAY,OAAO,MAAMK,CAAW,EAChD,GAGFC,EAASD,EAAaJ,CAAO,CACtC,CCxDe,SAARM,EAA+BC,EAAuD,CAC3F,GAAI,OAAOA,GAAU,UAAYA,IAAU,KACzC,MAAO,GAGT,IAAMC,EAAY,OAAO,eAAeD,CAAK,EAE7C,OAAIC,IAAc,MAAQA,IAAc,OAAO,UACtC,GAIF,CAAC,OAAO,OAAOD,EAAO,OAAO,WAAW,CACjD,CCjBe,SAARE,EAA0BC,EAAiC,CAChE,OAAO,OAAOA,GAAU,QAC1B,CCFe,SAARC,EACLC,EAAsCC,EACtC,CACA,IAAMC,EAAc,MAAM,QAAQD,CAAO,EAAIA,EAAU,CAACA,CAAO,EAE/D,OAAO,OAAO,YACZ,OAAO,QAAQD,CAAM,EAAE,OAAO,CAAC,CAACG,CAAG,IAAM,CAACD,EAAY,SAASC,CAAG,CAAC,CACrE,CACF,CCDe,SAARC,EAAuBC,EAAoBC,EAA6B,CAC7E,IAAMC,EAAQD,IAAa,OAAY,EAAID,EACrCG,EAAMF,GAAYD,EAExB,GAAI,CAAC,OAAO,UAAUE,CAAK,GAAK,CAAC,OAAO,UAAUC,CAAG,EACnD,MAAM,IAAI,UAAU,+CAA+CD,CAAK,eAAeC,CAAG,IAAI,EAGhG,IAAMC,EAASD,EAAMD,EAErB,GAAIE,EAAS,EACX,MAAM,IAAI,WAAW,yBAAyBF,CAAK,mCAAmCC,CAAG,IAAI,EAG/F,OAAO,MAAM,KAAK,CAAE,OAAAC,CAAO,EAAG,CAACC,EAAGC,IAAUJ,EAAQI,CAAK,CAC3D,CCtBe,SAARC,EAA0BC,EAAwB,CACvD,OAAOA,GAAO,WAAW,GAAK,OAAOA,CAAK,CAC5C,CCHe,SAARC,EAA2BC,EAAiB,CAEjD,OAAOA,EAAM,OAAO,CAACC,EAAMC,IAAUF,EAAM,QAAQC,CAAI,IAAMC,CAAK,CACpE",
|
|
6
|
+
"names": ["index_exports", "__export", "attempt", "capitalize", "compose", "isNumber", "isNumberLike", "isPlainObject", "isString", "omit", "range", "toString", "unique", "__toCommonJS", "attempt", "callback", "capitalize", "value", "compose", "functions", "value", "accumulator", "fn", "isNumber", "value", "options", "isNumberLike", "value", "options", "attempt", "falsyNumberValues", "truthyNumberValues", "numberValue", "isNumber", "isPlainObject", "value", "prototype", "isString", "value", "omit", "object", "omitted", "omittedKeys", "key", "range", "startOrEnd", "maybeEnd", "start", "end", "length", "_", "index", "toString", "value", "unique", "array", "item", "index"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@radham/utils",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A small bespoke utility library.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lib",
|
|
7
|
+
"library",
|
|
8
|
+
"utility",
|
|
9
|
+
"utilities"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/jbenner-radham/node-utils#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/jbenner-radham/node-utils/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/jbenner-radham/node-utils.git"
|
|
18
|
+
},
|
|
19
|
+
"license": "BSD-3-Clause",
|
|
20
|
+
"author": "James Benner <hello@jamesbenner.com> (https://www.jamesbenner.com/)",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "commonjs",
|
|
23
|
+
"exports": "./index.js",
|
|
24
|
+
"types": "../types/index.d.ts",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@eslint/compat": "^2.0.2",
|
|
27
|
+
"@eslint/json": "^1.0.0",
|
|
28
|
+
"@radham/changelog": "^0.1.1",
|
|
29
|
+
"@radham/eslint-config": "^13.0.0",
|
|
30
|
+
"@types/node": "^22.18.8",
|
|
31
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
32
|
+
"cspell": "^9.6.4",
|
|
33
|
+
"duo-build": "^0.2.1",
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
|
+
"globals": "^17.3.0",
|
|
36
|
+
"husky": "^9.1.7",
|
|
37
|
+
"lint-staged": "^16.2.7",
|
|
38
|
+
"np": "^11.0.2",
|
|
39
|
+
"rimraf": "^6.1.2",
|
|
40
|
+
"sort-package-json": "^3.6.1",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"vitest": "^4.0.18"
|
|
43
|
+
},
|
|
44
|
+
"packageManager": "pnpm@10.29.1",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function o(e){try{return e()}catch{}}function a(e){return e.charAt(0).toUpperCase()+e.slice(1)}function s(...e){return t=>e.reduce((r,n)=>n(r),t)}function u(e,t){return typeof e=="number"&&(!t?.finite||Number.isFinite(e))}function l(e,t){if(typeof e=="bigint")return!!t?.bigint;if(typeof e=="string"&&t?.bigint)return!!(o(()=>BigInt(e))??!1);if(typeof e=="string"&&["-Infinity","Infinity","NaN"].includes(e))return!t?.finite;let n=["",!1,null],i=[!0];if(n.includes(e)||i.includes(e))return!1;let f=Number(e);return typeof e!="number"&&Number.isNaN(f)?!1:u(f,t)}function p(e){if(typeof e!="object"||e===null)return!1;let t=Object.getPrototypeOf(e);return t!==null&&t!==Object.prototype?!1:!Object.hasOwn(e,Symbol.toStringTag)}function m(e){return typeof e=="string"}function c(e,t){let r=Array.isArray(t)?t:[t];return Object.fromEntries(Object.entries(e).filter(([n])=>!r.includes(n)))}function b(e,t){let r=t===void 0?0:e,n=t??e;if(!Number.isInteger(r)||!Number.isInteger(n))throw new TypeError(`Expected integer arguments, received start (${r}), and end (${n}).`);let i=n-r;if(i<0)throw new RangeError(`Invalid range: start (${r}) must not be greater than end (${n}).`);return Array.from({length:i},(f,y)=>r+y)}function d(e){return e?.toString?.()??String(e)}function g(e){return e.filter((t,r)=>e.indexOf(t)===r)}export{o as attempt,a as capitalize,s as compose,u as isNumber,l as isNumberLike,p as isPlainObject,m as isString,c as omit,b as range,d as toString,g as unique};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/attempt.ts", "../../src/capitalize.ts", "../../src/compose.ts", "../../src/is-number.ts", "../../src/is-number-like.ts", "../../src/is-plain-object.ts", "../../src/is-string.ts", "../../src/omit.ts", "../../src/range.ts", "../../src/to-string.ts", "../../src/unique.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Executes a function and returns its result, or `undefined` if it throws.\n *\n * @param callback - The function to execute.\n * @returns The return value of `callback`, or `undefined` if an error is thrown.\n *\n * @example\n * ```typescript\n * attempt(() => JSON.parse('{\"a\":1}')); // { a: 1 }\n * attempt(() => JSON.parse('invalid')); // undefined\n * ```\n */\nexport default function attempt<T>(callback: () => T): T | undefined {\n try {\n return callback();\n } catch { /* Do nothing. */ }\n}\n", "/**\n * Capitalizes the first character of a string.\n *\n * @param value - The string to capitalize.\n * @returns A new string with the first character in uppercase.\n *\n * @example\n * ```typescript\n * capitalize('hello'); // 'Hello'\n * ```\n */\nexport default function capitalize<T extends string>(value: T): Capitalize<T> {\n return (value.charAt(0).toUpperCase() + value.slice(1)) as Capitalize<T>;\n}\n", "/**\n * Composes multiple functions into a single function that applies them from left to right.\n *\n * @param functions - The functions to compose, each taking and returning the same type.\n * @returns A function that pipes a value through each function in order.\n *\n * @example\n * ```typescript\n * const addOne = (value: number) => value + 1;\n * const double = (value: number) => value * 2;\n *\n * compose(addOne, double)(3); // 8\n * ```\n */\nexport default function compose<T>(...functions: Array<(value: T) => T>): (value: T) => T {\n return (value: T) => functions.reduce((accumulator, fn) => fn(accumulator), value);\n}\n", "/**\n * Checks whether the given value is a number.\n *\n * @param value - The value to check.\n * @param options - Optional configuration.\n * @param options.finite - When `true`, only finite numbers are considered valid (`NaN` and\n * `Infinity` return `false`).\n * @returns `true` if `value` is a number, `false` otherwise.\n *\n * @example\n * ```typescript\n * isNumber(42); // true\n * isNumber('42'); // false\n * isNumber(NaN); // true\n * isNumber(NaN, { finite: true }); // false\n * isNumber(Infinity, { finite: true }); // false\n * ```\n */\nexport default function isNumber(\n value: unknown, options?: { finite?: boolean }\n): value is number {\n return typeof value === 'number' && (!options?.finite || Number.isFinite(value));\n}\n", "import attempt from './attempt.js';\nimport isNumber from './is-number.js';\n\n/**\n * Checks whether the given value is a number or can be coerced to one.\n *\n * @remarks\n * This function only considers actual numbers and strings that represent numbers as\n * number-like. Even though the values `''`, `false`, and `null` convert to `0`, and\n * `true` converts to `1`, none of these are considered number-like by this function.\n *\n * @param value - The value to check.\n * @param options - Optional configuration.\n * @param options.bigint - When `true`, bigints and strings that can be converted to\n * bigints are considered valid.\n * @param options.finite - When `true`, only finite numbers are considered valid (`NaN`,\n * `Infinity`, and their string equivalents return `false`).\n * @returns `true` if `value` is number-like, `false` otherwise.\n *\n * @example\n * ```typescript\n * isNumberLike(42); // true\n * isNumberLike('42'); // true\n * isNumberLike('3.14'); // true\n * isNumberLike('NaN'); // true\n * isNumberLike('NaN', { finite: true }); // false\n * isNumberLike('Infinity', { finite: true }); // false\n * isNumberLike('abc'); // false\n * isNumberLike(null); // false\n * isNumberLike(1n); // false\n * isNumberLike(1n, { bigint: true }); // true\n * isNumberLike('1n', { bigint: true }); // true\n * ```\n */\nexport default function isNumberLike(\n value: unknown, options?: { bigint?: boolean; finite?: boolean }\n): value is number {\n // `Number()` will coerce bigints to numbers, so we need to make this check.\n if (typeof value === 'bigint') {\n return Boolean(options?.bigint);\n }\n\n if (typeof value === 'string' && options?.bigint) {\n return Boolean(attempt(() => BigInt(value)) ?? false);\n }\n\n const infiniteNumberStrings = ['-Infinity', 'Infinity', 'NaN'];\n\n if (typeof value === 'string' && infiniteNumberStrings.includes(value)) {\n return !options?.finite;\n }\n\n // These values are converted to `0` by `Number()`.\n const falsyNumberValues = ['', false, null];\n\n // These values are converted to `1` by `Number()`.\n const truthyNumberValues = [true];\n\n if (\n falsyNumberValues.includes(value as boolean | null | string) ||\n truthyNumberValues.includes(value as boolean)\n ) {\n return false;\n }\n\n const numberValue = Number(value);\n\n if (typeof value !== 'number' && Number.isNaN(numberValue)) {\n return false;\n }\n\n return isNumber(numberValue, options);\n}\n", "/**\n * Checks whether the given value is a plain object.\n *\n * @remarks\n * A plain object is one created by the `Object` constructor, a `null` prototype, or an object\n * literal.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is a plain object, `false` otherwise.\n *\n * @example\n * ```typescript\n * isPlainObject({ a: 1 }); // true\n * isPlainObject([1, 2]); // false\n * ```\n */\nexport default function isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value) as unknown;\n\n if (prototype !== null && prototype !== Object.prototype) {\n return false;\n }\n\n // This is needed for `Atomics`, `Intl`, `JSON`, `Math`, and `Reflect`.\n return !Object.hasOwn(value, Symbol.toStringTag);\n}\n", "/**\n * Checks whether the given value is a string.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is a string, `false` otherwise.\n *\n * @example\n * ```typescript\n * isString('hello'); // true\n * isString(42); // false\n * ```\n */\nexport default function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n", "/**\n * Creates a new object with the specified keys omitted.\n *\n * @param object - The source object to omit keys from.\n * @param omitted - A key or array of keys to exclude from the result.\n * @returns A new object containing all entries from `object` except those with keys in `omitted`.\n *\n * @example\n * ```typescript\n * omit({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { b: 2 }\n * ```\n */\nexport default function omit(\n object: Record<PropertyKey, unknown>, omitted: PropertyKey | PropertyKey[]\n) {\n const omittedKeys = Array.isArray(omitted) ? omitted : [omitted];\n\n return Object.fromEntries(\n Object.entries(object).filter(([key]) => !omittedKeys.includes(key))\n );\n}\n", "/**\n * Creates an array of integers from `start` (inclusive) to `end` (exclusive).\n *\n * @remarks\n * When called with a single argument, it generates a range from `0` to that value.\n *\n * @param startOrEnd - The start of the range if `maybeEnd` is provided, otherwise the end.\n * @param maybeEnd - The end of the range (exclusive). Must be greater than or equal to `start`.\n * @returns An array of sequential integers.\n *\n * @throws {@link TypeError} If either argument is not a finite integer.\n * @throws {@link RangeError} If `start` is greater than `end`.\n *\n * @example\n * ```typescript\n * range(4); // [0, 1, 2, 3]\n * range(2, 5); // [2, 3, 4]\n * ```\n */\nexport default function range(startOrEnd: number, maybeEnd?: number): number[] {\n const start = maybeEnd === undefined ? 0 : startOrEnd;\n const end = maybeEnd ?? startOrEnd;\n\n if (!Number.isInteger(start) || !Number.isInteger(end)) {\n throw new TypeError(`Expected integer arguments, received start (${start}), and end (${end}).`);\n }\n\n const length = end - start;\n\n if (length < 0) {\n throw new RangeError(`Invalid range: start (${start}) must not be greater than end (${end}).`);\n }\n\n return Array.from({ length }, (_, index) => start + index);\n}\n", "/**\n * Converts a value to its string representation.\n *\n * @param value - The value to convert.\n * @returns The string representation of `value`.\n *\n * @example\n * ```typescript\n * toString(42); // '42'\n * toString(null); // 'null'\n * ```\n */\nexport default function toString(value: unknown): string {\n return value?.toString?.() ?? String(value);\n}\n", "/**\n * Returns a new array with duplicate values removed.\n *\n * @param array - The array to deduplicate.\n * @returns A new array containing only the first occurrence of each value.\n *\n * @example\n * ```typescript\n * unique([1, 2, 2, 3, 1]); // [1, 2, 3]\n * ```\n */\nexport default function unique<T>(array: T[]): T[] {\n // NOTE: This benchmarks significantly better than `return [...new Set(array)]`.\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n"],
|
|
5
|
+
"mappings": "AAYe,SAARA,EAA4BC,EAAkC,CACnE,GAAI,CACF,OAAOA,EAAS,CAClB,MAAQ,CAAoB,CAC9B,CCLe,SAARC,EAA8CC,EAAyB,CAC5E,OAAQA,EAAM,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAM,MAAM,CAAC,CACvD,CCCe,SAARC,KAA+BC,EAAoD,CACxF,OAAQC,GAAaD,EAAU,OAAO,CAACE,EAAaC,IAAOA,EAAGD,CAAW,EAAGD,CAAK,CACnF,CCEe,SAARG,EACLC,EAAgBC,EACC,CACjB,OAAO,OAAOD,GAAU,WAAa,CAACC,GAAS,QAAU,OAAO,SAASD,CAAK,EAChF,CCYe,SAARE,EACLC,EAAgBC,EACC,CAEjB,GAAI,OAAOD,GAAU,SACnB,MAAO,EAAQC,GAAS,OAG1B,GAAI,OAAOD,GAAU,UAAYC,GAAS,OACxC,MAAO,GAAQC,EAAQ,IAAM,OAAOF,CAAK,CAAC,GAAK,IAKjD,GAAI,OAAOA,GAAU,UAFS,CAAC,YAAa,WAAY,KAAK,EAEN,SAASA,CAAK,EACnE,MAAO,CAACC,GAAS,OAInB,IAAME,EAAoB,CAAC,GAAI,GAAO,IAAI,EAGpCC,EAAqB,CAAC,EAAI,EAEhC,GACED,EAAkB,SAASH,CAAgC,GAC3DI,EAAmB,SAASJ,CAAgB,EAE5C,MAAO,GAGT,IAAMK,EAAc,OAAOL,CAAK,EAEhC,OAAI,OAAOA,GAAU,UAAY,OAAO,MAAMK,CAAW,EAChD,GAGFC,EAASD,EAAaJ,CAAO,CACtC,CCxDe,SAARM,EAA+BC,EAAuD,CAC3F,GAAI,OAAOA,GAAU,UAAYA,IAAU,KACzC,MAAO,GAGT,IAAMC,EAAY,OAAO,eAAeD,CAAK,EAE7C,OAAIC,IAAc,MAAQA,IAAc,OAAO,UACtC,GAIF,CAAC,OAAO,OAAOD,EAAO,OAAO,WAAW,CACjD,CCjBe,SAARE,EAA0BC,EAAiC,CAChE,OAAO,OAAOA,GAAU,QAC1B,CCFe,SAARC,EACLC,EAAsCC,EACtC,CACA,IAAMC,EAAc,MAAM,QAAQD,CAAO,EAAIA,EAAU,CAACA,CAAO,EAE/D,OAAO,OAAO,YACZ,OAAO,QAAQD,CAAM,EAAE,OAAO,CAAC,CAACG,CAAG,IAAM,CAACD,EAAY,SAASC,CAAG,CAAC,CACrE,CACF,CCDe,SAARC,EAAuBC,EAAoBC,EAA6B,CAC7E,IAAMC,EAAQD,IAAa,OAAY,EAAID,EACrCG,EAAMF,GAAYD,EAExB,GAAI,CAAC,OAAO,UAAUE,CAAK,GAAK,CAAC,OAAO,UAAUC,CAAG,EACnD,MAAM,IAAI,UAAU,+CAA+CD,CAAK,eAAeC,CAAG,IAAI,EAGhG,IAAMC,EAASD,EAAMD,EAErB,GAAIE,EAAS,EACX,MAAM,IAAI,WAAW,yBAAyBF,CAAK,mCAAmCC,CAAG,IAAI,EAG/F,OAAO,MAAM,KAAK,CAAE,OAAAC,CAAO,EAAG,CAACC,EAAGC,IAAUJ,EAAQI,CAAK,CAC3D,CCtBe,SAARC,EAA0BC,EAAwB,CACvD,OAAOA,GAAO,WAAW,GAAK,OAAOA,CAAK,CAC5C,CCHe,SAARC,EAA2BC,EAAiB,CAEjD,OAAOA,EAAM,OAAO,CAACC,EAAMC,IAAUF,EAAM,QAAQC,CAAI,IAAMC,CAAK,CACpE",
|
|
6
|
+
"names": ["attempt", "callback", "capitalize", "value", "compose", "functions", "value", "accumulator", "fn", "isNumber", "value", "options", "isNumberLike", "value", "options", "attempt", "falsyNumberValues", "truthyNumberValues", "numberValue", "isNumber", "isPlainObject", "value", "prototype", "isString", "value", "omit", "object", "omitted", "omittedKeys", "key", "range", "startOrEnd", "maybeEnd", "start", "end", "length", "_", "index", "toString", "value", "unique", "array", "item", "index"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@radham/utils",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A small bespoke utility library.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lib",
|
|
7
|
+
"library",
|
|
8
|
+
"utility",
|
|
9
|
+
"utilities"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/jbenner-radham/node-utils#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/jbenner-radham/node-utils/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/jbenner-radham/node-utils.git"
|
|
18
|
+
},
|
|
19
|
+
"license": "BSD-3-Clause",
|
|
20
|
+
"author": "James Benner <hello@jamesbenner.com> (https://www.jamesbenner.com/)",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": "./index.js",
|
|
24
|
+
"types": "../types/index.d.ts",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@eslint/compat": "^2.0.2",
|
|
27
|
+
"@eslint/json": "^1.0.0",
|
|
28
|
+
"@radham/changelog": "^0.1.1",
|
|
29
|
+
"@radham/eslint-config": "^13.0.0",
|
|
30
|
+
"@types/node": "^22.18.8",
|
|
31
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
32
|
+
"cspell": "^9.6.4",
|
|
33
|
+
"duo-build": "^0.2.1",
|
|
34
|
+
"eslint": "^9.39.2",
|
|
35
|
+
"globals": "^17.3.0",
|
|
36
|
+
"husky": "^9.1.7",
|
|
37
|
+
"lint-staged": "^16.2.7",
|
|
38
|
+
"np": "^11.0.2",
|
|
39
|
+
"rimraf": "^6.1.2",
|
|
40
|
+
"sort-package-json": "^3.6.1",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"vitest": "^4.0.18"
|
|
43
|
+
},
|
|
44
|
+
"packageManager": "pnpm@10.29.1",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executes a function and returns its result, or `undefined` if it throws.
|
|
3
|
+
*
|
|
4
|
+
* @param callback - The function to execute.
|
|
5
|
+
* @returns The return value of `callback`, or `undefined` if an error is thrown.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* attempt(() => JSON.parse('{"a":1}')); // { a: 1 }
|
|
10
|
+
* attempt(() => JSON.parse('invalid')); // undefined
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export default function attempt<T>(callback: () => T): T | undefined;
|
|
14
|
+
//# sourceMappingURL=attempt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attempt.d.ts","sourceRoot":"","sources":["../../src/attempt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAInE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first character of a string.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The string to capitalize.
|
|
5
|
+
* @returns A new string with the first character in uppercase.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* capitalize('hello'); // 'Hello'
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export default function capitalize<T extends string>(value: T): Capitalize<T>;
|
|
13
|
+
//# sourceMappingURL=capitalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capitalize.d.ts","sourceRoot":"","sources":["../../src/capitalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAE5E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composes multiple functions into a single function that applies them from left to right.
|
|
3
|
+
*
|
|
4
|
+
* @param functions - The functions to compose, each taking and returning the same type.
|
|
5
|
+
* @returns A function that pipes a value through each function in order.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const addOne = (value: number) => value + 1;
|
|
10
|
+
* const double = (value: number) => value * 2;
|
|
11
|
+
*
|
|
12
|
+
* compose(addOne, double)(3); // 8
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export default function compose<T>(...functions: Array<(value: T) => T>): (value: T) => T;
|
|
16
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAExF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as attempt } from './attempt.js';
|
|
2
|
+
export { default as capitalize } from './capitalize.js';
|
|
3
|
+
export { default as compose } from './compose.js';
|
|
4
|
+
export { default as isNumber } from './is-number.js';
|
|
5
|
+
export { default as isNumberLike } from './is-number-like.js';
|
|
6
|
+
export { default as isPlainObject } from './is-plain-object.js';
|
|
7
|
+
export { default as isString } from './is-string.js';
|
|
8
|
+
export { default as omit } from './omit.js';
|
|
9
|
+
export { default as range } from './range.js';
|
|
10
|
+
export { default as toString } from './to-string.js';
|
|
11
|
+
export { default as unique } from './unique.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the given value is a number or can be coerced to one.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* This function only considers actual numbers and strings that represent numbers as
|
|
6
|
+
* number-like. Even though the values `''`, `false`, and `null` convert to `0`, and
|
|
7
|
+
* `true` converts to `1`, none of these are considered number-like by this function.
|
|
8
|
+
*
|
|
9
|
+
* @param value - The value to check.
|
|
10
|
+
* @param options - Optional configuration.
|
|
11
|
+
* @param options.bigint - When `true`, bigints and strings that can be converted to
|
|
12
|
+
* bigints are considered valid.
|
|
13
|
+
* @param options.finite - When `true`, only finite numbers are considered valid (`NaN`,
|
|
14
|
+
* `Infinity`, and their string equivalents return `false`).
|
|
15
|
+
* @returns `true` if `value` is number-like, `false` otherwise.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* isNumberLike(42); // true
|
|
20
|
+
* isNumberLike('42'); // true
|
|
21
|
+
* isNumberLike('3.14'); // true
|
|
22
|
+
* isNumberLike('NaN'); // true
|
|
23
|
+
* isNumberLike('NaN', { finite: true }); // false
|
|
24
|
+
* isNumberLike('Infinity', { finite: true }); // false
|
|
25
|
+
* isNumberLike('abc'); // false
|
|
26
|
+
* isNumberLike(null); // false
|
|
27
|
+
* isNumberLike(1n); // false
|
|
28
|
+
* isNumberLike(1n, { bigint: true }); // true
|
|
29
|
+
* isNumberLike('1n', { bigint: true }); // true
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export default function isNumberLike(value: unknown, options?: {
|
|
33
|
+
bigint?: boolean;
|
|
34
|
+
finite?: boolean;
|
|
35
|
+
}): value is number;
|
|
36
|
+
//# sourceMappingURL=is-number-like.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-number-like.d.ts","sourceRoot":"","sources":["../../src/is-number-like.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/D,KAAK,IAAI,MAAM,CAoCjB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the given value is a number.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The value to check.
|
|
5
|
+
* @param options - Optional configuration.
|
|
6
|
+
* @param options.finite - When `true`, only finite numbers are considered valid (`NaN` and
|
|
7
|
+
* `Infinity` return `false`).
|
|
8
|
+
* @returns `true` if `value` is a number, `false` otherwise.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* isNumber(42); // true
|
|
13
|
+
* isNumber('42'); // false
|
|
14
|
+
* isNumber(NaN); // true
|
|
15
|
+
* isNumber(NaN, { finite: true }); // false
|
|
16
|
+
* isNumber(Infinity, { finite: true }); // false
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export default function isNumber(value: unknown, options?: {
|
|
20
|
+
finite?: boolean;
|
|
21
|
+
}): value is number;
|
|
22
|
+
//# sourceMappingURL=is-number.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-number.d.ts","sourceRoot":"","sources":["../../src/is-number.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,KAAK,IAAI,MAAM,CAEjB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the given value is a plain object.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* A plain object is one created by the `Object` constructor, a `null` prototype, or an object
|
|
6
|
+
* literal.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The value to check.
|
|
9
|
+
* @returns `true` if `value` is a plain object, `false` otherwise.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* isPlainObject({ a: 1 }); // true
|
|
14
|
+
* isPlainObject([1, 2]); // false
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export default function isPlainObject(value: unknown): value is Record<PropertyKey, unknown>;
|
|
18
|
+
//# sourceMappingURL=is-plain-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-plain-object.d.ts","sourceRoot":"","sources":["../../src/is-plain-object.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAa3F"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the given value is a string.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The value to check.
|
|
5
|
+
* @returns `true` if `value` is a string, `false` otherwise.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* isString('hello'); // true
|
|
10
|
+
* isString(42); // false
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export default function isString(value: unknown): value is string;
|
|
14
|
+
//# sourceMappingURL=is-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-string.d.ts","sourceRoot":"","sources":["../../src/is-string.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a new object with the specified keys omitted.
|
|
3
|
+
*
|
|
4
|
+
* @param object - The source object to omit keys from.
|
|
5
|
+
* @param omitted - A key or array of keys to exclude from the result.
|
|
6
|
+
* @returns A new object containing all entries from `object` except those with keys in `omitted`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* omit({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { b: 2 }
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export default function omit(object: Record<PropertyKey, unknown>, omitted: PropertyKey | PropertyKey[]): {
|
|
14
|
+
[k: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=omit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"omit.d.ts","sourceRoot":"","sources":["../../src/omit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAC1B,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE;;EAO3E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an array of integers from `start` (inclusive) to `end` (exclusive).
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* When called with a single argument, it generates a range from `0` to that value.
|
|
6
|
+
*
|
|
7
|
+
* @param startOrEnd - The start of the range if `maybeEnd` is provided, otherwise the end.
|
|
8
|
+
* @param maybeEnd - The end of the range (exclusive). Must be greater than or equal to `start`.
|
|
9
|
+
* @returns An array of sequential integers.
|
|
10
|
+
*
|
|
11
|
+
* @throws {@link TypeError} If either argument is not a finite integer.
|
|
12
|
+
* @throws {@link RangeError} If `start` is greater than `end`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* range(4); // [0, 1, 2, 3]
|
|
17
|
+
* range(2, 5); // [2, 3, 4]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export default function range(startOrEnd: number, maybeEnd?: number): number[];
|
|
21
|
+
//# sourceMappingURL=range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAe7E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a value to its string representation.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The value to convert.
|
|
5
|
+
* @returns The string representation of `value`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* toString(42); // '42'
|
|
10
|
+
* toString(null); // 'null'
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export default function toString(value: unknown): string;
|
|
14
|
+
//# sourceMappingURL=to-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-string.d.ts","sourceRoot":"","sources":["../../src/to-string.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a new array with duplicate values removed.
|
|
3
|
+
*
|
|
4
|
+
* @param array - The array to deduplicate.
|
|
5
|
+
* @returns A new array containing only the first occurrence of each value.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* unique([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export default function unique<T>(array: T[]): T[];
|
|
13
|
+
//# sourceMappingURL=unique.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unique.d.ts","sourceRoot":"","sources":["../../src/unique.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAGjD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@radham/utils",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A small bespoke utility library.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lib",
|
|
7
|
+
"library",
|
|
8
|
+
"utility",
|
|
9
|
+
"utilities"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/jbenner-radham/node-utils#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/jbenner-radham/node-utils/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/jbenner-radham/node-utils.git"
|
|
18
|
+
},
|
|
19
|
+
"license": "BSD-3-Clause",
|
|
20
|
+
"author": "James Benner <hello@jamesbenner.com> (https://www.jamesbenner.com/)",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/types/index.d.ts",
|
|
26
|
+
"default": "./dist/esm/index.js"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/types/index.d.ts",
|
|
30
|
+
"default": "./dist/cjs/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"CHANGELOG.md"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"prebuild": "rimraf ./dist",
|
|
39
|
+
"build": "duo-build",
|
|
40
|
+
"lint": "eslint .",
|
|
41
|
+
"lint:fix": "eslint --fix .",
|
|
42
|
+
"prepare": "husky",
|
|
43
|
+
"prepublishOnly": "pnpm run build",
|
|
44
|
+
"spellcheck": "cspell --dot --gitignore .",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:coverage": "vitest run --coverage",
|
|
47
|
+
"test:watch": "vitest"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@eslint/compat": "^2.0.2",
|
|
51
|
+
"@eslint/json": "^1.0.0",
|
|
52
|
+
"@radham/changelog": "^0.1.1",
|
|
53
|
+
"@radham/eslint-config": "^13.0.0",
|
|
54
|
+
"@types/node": "^22.18.8",
|
|
55
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
56
|
+
"cspell": "^9.6.4",
|
|
57
|
+
"duo-build": "^0.2.1",
|
|
58
|
+
"eslint": "^9.39.2",
|
|
59
|
+
"globals": "^17.3.0",
|
|
60
|
+
"husky": "^9.1.7",
|
|
61
|
+
"lint-staged": "^16.2.7",
|
|
62
|
+
"np": "^11.0.2",
|
|
63
|
+
"rimraf": "^6.1.2",
|
|
64
|
+
"sort-package-json": "^3.6.1",
|
|
65
|
+
"typescript": "^5.9.3",
|
|
66
|
+
"vitest": "^4.0.18"
|
|
67
|
+
},
|
|
68
|
+
"packageManager": "pnpm@10.29.1",
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=22"
|
|
71
|
+
}
|
|
72
|
+
}
|