@nejs/basic-extensions 1.0.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/LICENSE +21 -0
- package/README.md +65 -0
- package/bin/build +30 -0
- package/bin/fixup +13 -0
- package/dist/.gitkeep +0 -0
- package/dist/cjs/arrayextensions.d.ts +10 -0
- package/dist/cjs/arrayextensions.js +39 -0
- package/dist/cjs/functionextensions.d.ts +10 -0
- package/dist/cjs/functionextensions.js +80 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.js +30 -0
- package/dist/cjs/objectextensions.d.ts +10 -0
- package/dist/cjs/objectextensions.js +79 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/reflectextensions.d.ts +14 -0
- package/dist/cjs/reflectextensions.js +87 -0
- package/dist/mjs/arrayextensions.d.ts +10 -0
- package/dist/mjs/arrayextensions.js +36 -0
- package/dist/mjs/functionextensions.d.ts +10 -0
- package/dist/mjs/functionextensions.js +77 -0
- package/dist/mjs/index.d.ts +7 -0
- package/dist/mjs/index.js +22 -0
- package/dist/mjs/objectextensions.d.ts +10 -0
- package/dist/mjs/objectextensions.js +76 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/reflectextensions.d.ts +14 -0
- package/dist/mjs/reflectextensions.js +84 -0
- package/package.json +48 -0
- package/src/.gitkeep +0 -0
- package/src/arrayextensions.js +38 -0
- package/src/functionextensions.js +88 -0
- package/src/index.js +32 -0
- package/src/objectextensions.js +81 -0
- package/src/reflectextensions.js +89 -0
- package/tests/.gitkeep +0 -0
- package/tests/index.test.js +36 -0
- package/tsconfig.base.json +25 -0
- package/tsconfig.cjs.json +8 -0
- package/tsconfig.esm.json +8 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function enableAll(owners: any): void;
|
|
2
|
+
export function disableAll(owners: any): void;
|
|
3
|
+
import { ObjectExtensions } from './objectextensions.js';
|
|
4
|
+
import { FunctionExtensions } from './functionextensions.js';
|
|
5
|
+
import { ReflectExtensions } from './reflectextensions.js';
|
|
6
|
+
import { ArrayPrototypeExtensions } from './arrayextensions.js';
|
|
7
|
+
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, ArrayPrototypeExtensions };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FunctionExtensions } from './functionextensions.js';
|
|
2
|
+
import { ObjectExtensions } from './objectextensions.js';
|
|
3
|
+
import { ReflectExtensions } from './reflectextensions.js';
|
|
4
|
+
import { ArrayPrototypeExtensions } from './arrayextensions.js';
|
|
5
|
+
import { Patch } from '@nejs/extension';
|
|
6
|
+
const Owners = [
|
|
7
|
+
Object,
|
|
8
|
+
Function,
|
|
9
|
+
Reflect,
|
|
10
|
+
Array.prototype,
|
|
11
|
+
];
|
|
12
|
+
export function enableAll(owners) {
|
|
13
|
+
(owners || Owners).forEach(owner => {
|
|
14
|
+
Patch.enableFor(owner);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function disableAll(owners) {
|
|
18
|
+
(owners || Owners).forEach(owner => {
|
|
19
|
+
Patch.disableFor(owner);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, ArrayPrototypeExtensions, };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ObjectExtensions` is a patch for the JavaScript built-in `Object` class. It
|
|
3
|
+
* adds utility methods to the `Object` class without modifying the global namespace
|
|
4
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
5
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
6
|
+
* enhancing the capabilities of the standard `Object` class with additional
|
|
7
|
+
* utility functions.
|
|
8
|
+
*/
|
|
9
|
+
export const ObjectExtensions: Patch;
|
|
10
|
+
import { Patch } from '@nejs/extension';
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension';
|
|
2
|
+
/**
|
|
3
|
+
* `ObjectExtensions` is a patch for the JavaScript built-in `Object` class. It
|
|
4
|
+
* adds utility methods to the `Object` class without modifying the global namespace
|
|
5
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
6
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
7
|
+
* enhancing the capabilities of the standard `Object` class with additional
|
|
8
|
+
* utility functions.
|
|
9
|
+
*/
|
|
10
|
+
export const ObjectExtensions = new Patch(Object, {
|
|
11
|
+
/**
|
|
12
|
+
* Checks if the given value is a valid key for an object. In JavaScript, a valid
|
|
13
|
+
* key can be either a string or a symbol. This method is useful for validating
|
|
14
|
+
* object keys before using them in operations like setting or getting object properties.
|
|
15
|
+
*
|
|
16
|
+
* @param {*} value - The value to be checked.
|
|
17
|
+
* @returns {boolean} - Returns `true` if the value is a valid object key (string or symbol),
|
|
18
|
+
* otherwise `false`.
|
|
19
|
+
*/
|
|
20
|
+
isValidKey(value) {
|
|
21
|
+
return (typeof value === 'string' || typeof value === 'symbol');
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* Determines if the provided value is an object. This method checks whether the
|
|
25
|
+
* value is an instance of `Object` or if its type is 'object'. It's a utility
|
|
26
|
+
* method for type-checking, ensuring that a value is an object before performing
|
|
27
|
+
* operations that are specific to objects.
|
|
28
|
+
*
|
|
29
|
+
* @param {*} value - The value to be checked.
|
|
30
|
+
* @returns {boolean} - Returns `true` if the value is an object, otherwise `false`.
|
|
31
|
+
*/
|
|
32
|
+
isObject(value) {
|
|
33
|
+
return value && (value instanceof Object || typeof value === 'object');
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves the string tag of an object. The string tag is a representation of
|
|
37
|
+
* the object's type, as defined by its `Object.prototype.toString` method. This
|
|
38
|
+
* utility method is helpful for getting a more descriptive type of an object than
|
|
39
|
+
* what is returned by the `typeof` operator, especially for custom objects.
|
|
40
|
+
*
|
|
41
|
+
* @param {*} value - The object whose string tag is to be retrieved.
|
|
42
|
+
* @returns {string} - The string tag of the object, indicating its type.
|
|
43
|
+
*/
|
|
44
|
+
getStringTag(value) {
|
|
45
|
+
return /(\w+)]/.exec(Object.prototype.toString.call(value))[1];
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Determines the type of the given value based on its string tag. This method
|
|
49
|
+
* uses `Object.getStringTag` to obtain the string tag of the value, which
|
|
50
|
+
* represents its more specific type (e.g., Array, Map, Set) rather than just
|
|
51
|
+
* 'object'. The method then maps this string tag to the corresponding type
|
|
52
|
+
* present in the provided `owner` object, which defaults to `globalThis`.
|
|
53
|
+
* This utility method is especially useful for identifying the specific
|
|
54
|
+
* constructor or class of an object, beyond the basic types identified by
|
|
55
|
+
* the `typeof` operator.
|
|
56
|
+
*
|
|
57
|
+
* @param {any} value - The value whose type is to be determined.
|
|
58
|
+
* @param {object} [owner=globalThis] - The object in which to look up the
|
|
59
|
+
* constructor corresponding to the string tag. Defaults to `globalThis`, which
|
|
60
|
+
* covers global constructors like `Array`, `Object`, etc.
|
|
61
|
+
* @returns {Function|object|null|undefined} - Returns the constructor or type
|
|
62
|
+
* of the value based on its string tag. For 'Null' and 'Undefined', it returns
|
|
63
|
+
* `null` and `undefined`, respectively. For other types, it returns the
|
|
64
|
+
* corresponding constructor (e.g., `Array` for arrays) if available in the
|
|
65
|
+
* `owner` object.
|
|
66
|
+
*/
|
|
67
|
+
getType(value, owner = globalThis) {
|
|
68
|
+
const stringTag = Object.getStringTag(value);
|
|
69
|
+
switch (stringTag) {
|
|
70
|
+
case 'Null': return null;
|
|
71
|
+
case 'Undefined': return undefined;
|
|
72
|
+
default:
|
|
73
|
+
return owner[stringTag];
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `ReflectExtensions` class is a patch applied to the built-in JavaScript
|
|
3
|
+
* `Reflect` object. It extends `Reflect` with additional utility methods that
|
|
4
|
+
* enhance its capabilities. These methods provide more advanced ways of
|
|
5
|
+
* interacting with object properties, such as checking for the presence of
|
|
6
|
+
* multiple keys at once (`hasAll`) or verifying if at least one specified key
|
|
7
|
+
* exists in an object (`hasSome`). This class is part of the `@nejs/extension`
|
|
8
|
+
* library and is designed to offer these extended functionalities in a way
|
|
9
|
+
* that is consistent with the existing `Reflect` API, making it intuitive for
|
|
10
|
+
* developers who are already familiar with standard reflection methods in
|
|
11
|
+
* JavaScript.
|
|
12
|
+
*/
|
|
13
|
+
export const ReflectExtensions: Patch;
|
|
14
|
+
import { Patch } from '@nejs/extension';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension';
|
|
2
|
+
/**
|
|
3
|
+
* The `ReflectExtensions` class is a patch applied to the built-in JavaScript
|
|
4
|
+
* `Reflect` object. It extends `Reflect` with additional utility methods that
|
|
5
|
+
* enhance its capabilities. These methods provide more advanced ways of
|
|
6
|
+
* interacting with object properties, such as checking for the presence of
|
|
7
|
+
* multiple keys at once (`hasAll`) or verifying if at least one specified key
|
|
8
|
+
* exists in an object (`hasSome`). This class is part of the `@nejs/extension`
|
|
9
|
+
* library and is designed to offer these extended functionalities in a way
|
|
10
|
+
* that is consistent with the existing `Reflect` API, making it intuitive for
|
|
11
|
+
* developers who are already familiar with standard reflection methods in
|
|
12
|
+
* JavaScript.
|
|
13
|
+
*/
|
|
14
|
+
export const ReflectExtensions = new Patch(Reflect, {
|
|
15
|
+
/**
|
|
16
|
+
* The function checks if an object has all the specified keys.
|
|
17
|
+
*
|
|
18
|
+
* @param object - The `object` parameter is the object that we want to
|
|
19
|
+
* check if it has all the specified keys.
|
|
20
|
+
* @param keys - The `keys` parameter is a rest parameter, which means
|
|
21
|
+
* it can accept any number of arguments. In this case, it is expected
|
|
22
|
+
* to receive multiple keys as arguments.
|
|
23
|
+
* @returns a boolean value.
|
|
24
|
+
*/
|
|
25
|
+
hasAll(object, ...keys) {
|
|
26
|
+
return Object.isObject(object) && (keys.flat(Infinity)
|
|
27
|
+
.map(key => Reflect.has(object, key))
|
|
28
|
+
.every(has => has));
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* The function checks if an object has at least one of the specified keys.
|
|
32
|
+
*
|
|
33
|
+
* @param object - The `object` parameter is the object that we want to check
|
|
34
|
+
* for the presence of certain keys.
|
|
35
|
+
* @param keys - The `keys` parameter is a rest parameter, which means it can
|
|
36
|
+
* accept any number of arguments. These arguments are the keys that we want
|
|
37
|
+
* to check if they exist in the `object`.
|
|
38
|
+
* @returns The function `hasSome` returns a boolean value indicating whether
|
|
39
|
+
* at least one of the keys provided as arguments exists in the given object.
|
|
40
|
+
*/
|
|
41
|
+
hasSome(object, ...keys) {
|
|
42
|
+
return Object.isObject(object) && (keys.flat(Infinity)
|
|
43
|
+
.map(key => Reflect.has(object, key))
|
|
44
|
+
.some(has => has));
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves an array of [key, descriptor] pairs for each property of the
|
|
48
|
+
* provided object. This method is akin to `Object.entries` but includes
|
|
49
|
+
* property descriptors instead of the property values. It's useful for cases
|
|
50
|
+
* where you need detailed information about properties, including their
|
|
51
|
+
* configurability, enumerability, and accessors.
|
|
52
|
+
*
|
|
53
|
+
* @param {object} object - The object whose property entries are to be
|
|
54
|
+
* retrieved.
|
|
55
|
+
* @returns {Array} An array of [key, descriptor] pairs, where each pair
|
|
56
|
+
* consists of the property name (key) and its descriptor. Returns an empty
|
|
57
|
+
* array if the input is not a valid object.
|
|
58
|
+
*/
|
|
59
|
+
entries(object) {
|
|
60
|
+
if (!object || typeof object !== 'object') {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return Reflect.ownKeys(object).map(key => [
|
|
64
|
+
key, Object.getOwnPropertyDescriptor(object, key)
|
|
65
|
+
]);
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Retrieves an array of values from the property descriptors of the given
|
|
69
|
+
* object. This method works similarly to `Object.values` but operates on
|
|
70
|
+
* property descriptors instead. It's useful when you need the values of
|
|
71
|
+
* properties including getters, setters, and other descriptor-specific
|
|
72
|
+
* attributes.
|
|
73
|
+
*
|
|
74
|
+
* @param {object} object - The object whose property values are to be
|
|
75
|
+
* retrieved.
|
|
76
|
+
* @returns {Array} An array of values extracted from the object's property
|
|
77
|
+
* descriptors. The values correspond to the `value` attribute in each
|
|
78
|
+
* property's descriptor. Returns an empty array if the input is not a valid
|
|
79
|
+
* object.
|
|
80
|
+
*/
|
|
81
|
+
values(object) {
|
|
82
|
+
return Reflect.entries.map(([, value]) => value);
|
|
83
|
+
}
|
|
84
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "Brielle Harrison <nyteshade at gmail.com>",
|
|
3
|
+
"description": "Basic but commonly used extensions",
|
|
4
|
+
"devDependencies": {
|
|
5
|
+
"@jest/expect": "^29.7.0",
|
|
6
|
+
"jest": "^29.7.0",
|
|
7
|
+
"jest-cli": "^29.7.0",
|
|
8
|
+
"jest-localstorage-mock": "^2.4.26",
|
|
9
|
+
"prompts": "^2.4.2",
|
|
10
|
+
"typescript": "^5.2.2"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=16"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./dist/mjs/index.js",
|
|
18
|
+
"require": "./dist/cjs/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"jest": {
|
|
22
|
+
"verbose": true,
|
|
23
|
+
"setupFiles": [
|
|
24
|
+
"jest-localstorage-mock"
|
|
25
|
+
],
|
|
26
|
+
"transform": {
|
|
27
|
+
"^.+\\.[t|j]sx?$": "babel-jest"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"javascript",
|
|
32
|
+
"browser",
|
|
33
|
+
"localStorage"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"main": "dist/cjs/index.js",
|
|
37
|
+
"module": "dist/mjs/index.js",
|
|
38
|
+
"name": "@nejs/basic-extensions",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "bin/build",
|
|
41
|
+
"test": "jest"
|
|
42
|
+
},
|
|
43
|
+
"type": "module",
|
|
44
|
+
"version": "1.0.0",
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@nejs/extension": "^1.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `ArrayPrototypeExtensions` patch extends the prototype of the built-in
|
|
5
|
+
* JavaScript `Array` with additional properties for convenience and improved
|
|
6
|
+
* readability. By applying this patch, all array instances gain new getter
|
|
7
|
+
* properties `first` and `last`, which provide quick access to the first and
|
|
8
|
+
* last elements of the array, respectively. This enhancement simplifies common
|
|
9
|
+
* operations on arrays and makes code more expressive and concise.
|
|
10
|
+
*/
|
|
11
|
+
export const ArrayPrototypeExtensions = new Patch(Array.prototype, {
|
|
12
|
+
/**
|
|
13
|
+
* A getter property that returns the first element of the array. If the
|
|
14
|
+
* array is empty, it returns `undefined`. This property is useful for
|
|
15
|
+
* scenarios where you need to quickly access the first item of an array
|
|
16
|
+
* without the need for additional checks or method calls.
|
|
17
|
+
*
|
|
18
|
+
* @returns {*} The first element of the array or `undefined` if the array
|
|
19
|
+
* is empty.
|
|
20
|
+
*/
|
|
21
|
+
get first() {
|
|
22
|
+
return this[0];
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A getter property that returns the last element of the array. It
|
|
27
|
+
* calculates the last index based on the array's length. If the array is
|
|
28
|
+
* empty, it returns `undefined`. This property is beneficial when you need
|
|
29
|
+
* to access the last item in an array, improving code readability and
|
|
30
|
+
* avoiding manual index calculation.
|
|
31
|
+
*
|
|
32
|
+
* @returns {*} The last element of the array or `undefined` if the
|
|
33
|
+
* array is empty.
|
|
34
|
+
*/
|
|
35
|
+
get last() {
|
|
36
|
+
return this[this.length - 1];
|
|
37
|
+
}
|
|
38
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `FunctionExtensions` class is a patch applied to the built-in JavaScript `Function`
|
|
5
|
+
* constructor. It extends `Function` with additional utility methods for determining the
|
|
6
|
+
* specific type or nature of function-like objects. These methods allow developers to
|
|
7
|
+
* distinguish between classes, regular functions, async functions, and arrow functions
|
|
8
|
+
* in a more intuitive and straightforward manner. This class is part of the `@nejs/extension`
|
|
9
|
+
* library and enhances the capabilities of function handling and introspection in JavaScript.
|
|
10
|
+
*/
|
|
11
|
+
export const FunctionExtensions = new Patch(Function, {
|
|
12
|
+
/**
|
|
13
|
+
* Determines if a given value is a class. It checks if the value is an instance of
|
|
14
|
+
* `Function` and if its string representation includes the keyword 'class'. This method
|
|
15
|
+
* is useful for distinguishing classes from other function types in JavaScript.
|
|
16
|
+
*
|
|
17
|
+
* @param {*} value - The value to be checked.
|
|
18
|
+
* @returns {boolean} Returns `true` if the value is a class, otherwise `false`.
|
|
19
|
+
*/
|
|
20
|
+
isClass(value) {
|
|
21
|
+
return value instanceof Function && String(value).includes('class');
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Checks if a given value is a regular function. This method verifies if the value is
|
|
26
|
+
* an instance of `Function`, which includes regular functions, classes, and async
|
|
27
|
+
* functions but excludes arrow functions.
|
|
28
|
+
*
|
|
29
|
+
* @param {*} value - The value to be checked.
|
|
30
|
+
* @returns {boolean} Returns `true` if the value is a regular function, otherwise `false`.
|
|
31
|
+
*/
|
|
32
|
+
isFunction(value) {
|
|
33
|
+
return value instanceof Function;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Determines if a given value is an asynchronous function. It checks if the value is an
|
|
38
|
+
* instance of `Function` and if its string representation includes the keyword 'Async'.
|
|
39
|
+
* This method is particularly useful for identifying async functions.
|
|
40
|
+
*
|
|
41
|
+
* @param {*} value - The value to be checked.
|
|
42
|
+
* @returns {boolean} Returns `true` if the value is an async function, otherwise `false`.
|
|
43
|
+
*/
|
|
44
|
+
isAsync(value) {
|
|
45
|
+
const stringTag = /(\w+)]/g.exec(Object.prototype.toString.call(value))[1]
|
|
46
|
+
return (
|
|
47
|
+
value instanceof Function &&
|
|
48
|
+
stringTag.includes('Async')
|
|
49
|
+
)
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a given value is an arrow function. It verifies if the value is an instance
|
|
54
|
+
* of `Function`, if its string representation includes the '=>' symbol, and if it lacks
|
|
55
|
+
* a prototype, which is a characteristic of arrow functions in JavaScript.
|
|
56
|
+
*
|
|
57
|
+
* @param {*} value - The value to be checked.
|
|
58
|
+
* @returns {boolean} Returns `true` if the value is an arrow function, otherwise `false`.
|
|
59
|
+
*/
|
|
60
|
+
isBigArrow(value) {
|
|
61
|
+
return (
|
|
62
|
+
value instanceof Function &&
|
|
63
|
+
String(value).includes('=>') &&
|
|
64
|
+
!String(value).startsWith('bound') &&
|
|
65
|
+
!Reflect.has(value, 'prototype')
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Determines if a given value is a bound function. Bound functions are created using
|
|
71
|
+
* the `Function.prototype.bind` method, which allows setting the `this` value at the
|
|
72
|
+
* time of binding. This method checks if the value is an instance of `Function`, if
|
|
73
|
+
* its string representation starts with 'bound', and if it lacks a `prototype`
|
|
74
|
+
* property. These characteristics are indicative of bound functions in JavaScript.
|
|
75
|
+
*
|
|
76
|
+
* @param {*} value - The value to be checked, typically a function.
|
|
77
|
+
* @returns {boolean} Returns `true` if the value is a bound function, otherwise
|
|
78
|
+
* `false`. Bound functions have a specific format in their string representation
|
|
79
|
+
* and do not have their own `prototype` property.
|
|
80
|
+
*/
|
|
81
|
+
isBound(value) {
|
|
82
|
+
return (
|
|
83
|
+
value instanceof Function &&
|
|
84
|
+
String(value).startsWith('bound') &&
|
|
85
|
+
!Reflect.has(value, 'prototype')
|
|
86
|
+
)
|
|
87
|
+
},
|
|
88
|
+
})
|
package/src/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FunctionExtensions } from './functionextensions.js'
|
|
2
|
+
import { ObjectExtensions } from './objectextensions.js'
|
|
3
|
+
import { ReflectExtensions } from './reflectextensions.js'
|
|
4
|
+
import { ArrayPrototypeExtensions } from './arrayextensions.js'
|
|
5
|
+
import { Patch } from '@nejs/extension'
|
|
6
|
+
|
|
7
|
+
const Owners = [
|
|
8
|
+
Object,
|
|
9
|
+
Function,
|
|
10
|
+
Reflect,
|
|
11
|
+
|
|
12
|
+
Array.prototype,
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
export function enableAll(owners) {
|
|
16
|
+
(owners || Owners).forEach(owner => {
|
|
17
|
+
Patch.enableFor(owner)
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function disableAll(owners) {
|
|
22
|
+
(owners || Owners).forEach(owner => {
|
|
23
|
+
Patch.disableFor(owner)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
ObjectExtensions,
|
|
29
|
+
FunctionExtensions,
|
|
30
|
+
ReflectExtensions,
|
|
31
|
+
ArrayPrototypeExtensions,
|
|
32
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `ObjectExtensions` is a patch for the JavaScript built-in `Object` class. It
|
|
5
|
+
* adds utility methods to the `Object` class without modifying the global namespace
|
|
6
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
7
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
8
|
+
* enhancing the capabilities of the standard `Object` class with additional
|
|
9
|
+
* utility functions.
|
|
10
|
+
*/
|
|
11
|
+
export const ObjectExtensions = new Patch(Object, {
|
|
12
|
+
/**
|
|
13
|
+
* Checks if the given value is a valid key for an object. In JavaScript, a valid
|
|
14
|
+
* key can be either a string or a symbol. This method is useful for validating
|
|
15
|
+
* object keys before using them in operations like setting or getting object properties.
|
|
16
|
+
*
|
|
17
|
+
* @param {*} value - The value to be checked.
|
|
18
|
+
* @returns {boolean} - Returns `true` if the value is a valid object key (string or symbol),
|
|
19
|
+
* otherwise `false`.
|
|
20
|
+
*/
|
|
21
|
+
isValidKey(value) {
|
|
22
|
+
return (typeof value === 'string' || typeof value === 'symbol');
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Determines if the provided value is an object. This method checks whether the
|
|
27
|
+
* value is an instance of `Object` or if its type is 'object'. It's a utility
|
|
28
|
+
* method for type-checking, ensuring that a value is an object before performing
|
|
29
|
+
* operations that are specific to objects.
|
|
30
|
+
*
|
|
31
|
+
* @param {*} value - The value to be checked.
|
|
32
|
+
* @returns {boolean} - Returns `true` if the value is an object, otherwise `false`.
|
|
33
|
+
*/
|
|
34
|
+
isObject(value) {
|
|
35
|
+
return value && (value instanceof Object || typeof value === 'object');
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Retrieves the string tag of an object. The string tag is a representation of
|
|
40
|
+
* the object's type, as defined by its `Object.prototype.toString` method. This
|
|
41
|
+
* utility method is helpful for getting a more descriptive type of an object than
|
|
42
|
+
* what is returned by the `typeof` operator, especially for custom objects.
|
|
43
|
+
*
|
|
44
|
+
* @param {*} value - The object whose string tag is to be retrieved.
|
|
45
|
+
* @returns {string} - The string tag of the object, indicating its type.
|
|
46
|
+
*/
|
|
47
|
+
getStringTag(value) {
|
|
48
|
+
return /(\w+)]/.exec(Object.prototype.toString.call(value))[1];
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Determines the type of the given value based on its string tag. This method
|
|
53
|
+
* uses `Object.getStringTag` to obtain the string tag of the value, which
|
|
54
|
+
* represents its more specific type (e.g., Array, Map, Set) rather than just
|
|
55
|
+
* 'object'. The method then maps this string tag to the corresponding type
|
|
56
|
+
* present in the provided `owner` object, which defaults to `globalThis`.
|
|
57
|
+
* This utility method is especially useful for identifying the specific
|
|
58
|
+
* constructor or class of an object, beyond the basic types identified by
|
|
59
|
+
* the `typeof` operator.
|
|
60
|
+
*
|
|
61
|
+
* @param {any} value - The value whose type is to be determined.
|
|
62
|
+
* @param {object} [owner=globalThis] - The object in which to look up the
|
|
63
|
+
* constructor corresponding to the string tag. Defaults to `globalThis`, which
|
|
64
|
+
* covers global constructors like `Array`, `Object`, etc.
|
|
65
|
+
* @returns {Function|object|null|undefined} - Returns the constructor or type
|
|
66
|
+
* of the value based on its string tag. For 'Null' and 'Undefined', it returns
|
|
67
|
+
* `null` and `undefined`, respectively. For other types, it returns the
|
|
68
|
+
* corresponding constructor (e.g., `Array` for arrays) if available in the
|
|
69
|
+
* `owner` object.
|
|
70
|
+
*/
|
|
71
|
+
getType(value, owner = globalThis) {
|
|
72
|
+
const stringTag = Object.getStringTag(value)
|
|
73
|
+
|
|
74
|
+
switch (stringTag) {
|
|
75
|
+
case 'Null': return null
|
|
76
|
+
case 'Undefined': return undefined
|
|
77
|
+
default:
|
|
78
|
+
return owner[stringTag]
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `ReflectExtensions` class is a patch applied to the built-in JavaScript
|
|
5
|
+
* `Reflect` object. It extends `Reflect` with additional utility methods that
|
|
6
|
+
* enhance its capabilities. These methods provide more advanced ways of
|
|
7
|
+
* interacting with object properties, such as checking for the presence of
|
|
8
|
+
* multiple keys at once (`hasAll`) or verifying if at least one specified key
|
|
9
|
+
* exists in an object (`hasSome`). This class is part of the `@nejs/extension`
|
|
10
|
+
* library and is designed to offer these extended functionalities in a way
|
|
11
|
+
* that is consistent with the existing `Reflect` API, making it intuitive for
|
|
12
|
+
* developers who are already familiar with standard reflection methods in
|
|
13
|
+
* JavaScript.
|
|
14
|
+
*/
|
|
15
|
+
export const ReflectExtensions = new Patch(Reflect, {
|
|
16
|
+
/**
|
|
17
|
+
* The function checks if an object has all the specified keys.
|
|
18
|
+
*
|
|
19
|
+
* @param object - The `object` parameter is the object that we want to
|
|
20
|
+
* check if it has all the specified keys.
|
|
21
|
+
* @param keys - The `keys` parameter is a rest parameter, which means
|
|
22
|
+
* it can accept any number of arguments. In this case, it is expected
|
|
23
|
+
* to receive multiple keys as arguments.
|
|
24
|
+
* @returns a boolean value.
|
|
25
|
+
*/
|
|
26
|
+
hasAll(object, ...keys) {
|
|
27
|
+
return Object.isObject(object) && (keys.flat(Infinity)
|
|
28
|
+
.map(key => Reflect.has(object, key))
|
|
29
|
+
.every(has => has)
|
|
30
|
+
)
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The function checks if an object has at least one of the specified keys.
|
|
35
|
+
*
|
|
36
|
+
* @param object - The `object` parameter is the object that we want to check
|
|
37
|
+
* for the presence of certain keys.
|
|
38
|
+
* @param keys - The `keys` parameter is a rest parameter, which means it can
|
|
39
|
+
* accept any number of arguments. These arguments are the keys that we want
|
|
40
|
+
* to check if they exist in the `object`.
|
|
41
|
+
* @returns The function `hasSome` returns a boolean value indicating whether
|
|
42
|
+
* at least one of the keys provided as arguments exists in the given object.
|
|
43
|
+
*/
|
|
44
|
+
hasSome(object, ...keys) {
|
|
45
|
+
return Object.isObject(object) && (keys.flat(Infinity)
|
|
46
|
+
.map(key => Reflect.has(object, key))
|
|
47
|
+
.some(has => has)
|
|
48
|
+
)
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Retrieves an array of [key, descriptor] pairs for each property of the
|
|
53
|
+
* provided object. This method is akin to `Object.entries` but includes
|
|
54
|
+
* property descriptors instead of the property values. It's useful for cases
|
|
55
|
+
* where you need detailed information about properties, including their
|
|
56
|
+
* configurability, enumerability, and accessors.
|
|
57
|
+
*
|
|
58
|
+
* @param {object} object - The object whose property entries are to be
|
|
59
|
+
* retrieved.
|
|
60
|
+
* @returns {Array} An array of [key, descriptor] pairs, where each pair
|
|
61
|
+
* consists of the property name (key) and its descriptor. Returns an empty
|
|
62
|
+
* array if the input is not a valid object.
|
|
63
|
+
*/
|
|
64
|
+
entries(object) {
|
|
65
|
+
if (!object || typeof object !== 'object') { return [] }
|
|
66
|
+
|
|
67
|
+
return Reflect.ownKeys(object).map(key => [
|
|
68
|
+
key, Object.getOwnPropertyDescriptor(object, key)
|
|
69
|
+
])
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves an array of values from the property descriptors of the given
|
|
74
|
+
* object. This method works similarly to `Object.values` but operates on
|
|
75
|
+
* property descriptors instead. It's useful when you need the values of
|
|
76
|
+
* properties including getters, setters, and other descriptor-specific
|
|
77
|
+
* attributes.
|
|
78
|
+
*
|
|
79
|
+
* @param {object} object - The object whose property values are to be
|
|
80
|
+
* retrieved.
|
|
81
|
+
* @returns {Array} An array of values extracted from the object's property
|
|
82
|
+
* descriptors. The values correspond to the `value` attribute in each
|
|
83
|
+
* property's descriptor. Returns an empty array if the input is not a valid
|
|
84
|
+
* object.
|
|
85
|
+
*/
|
|
86
|
+
values(object) {
|
|
87
|
+
return Reflect.entries.map(([,value]) => value)
|
|
88
|
+
}
|
|
89
|
+
})
|
package/tests/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { enableAll, disableAll } = require('../dist/cjs/index.js')
|
|
2
|
+
|
|
3
|
+
describe('Enabled extensions', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
enableAll()
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
disableAll()
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('first returns the first element of the array', () => {
|
|
13
|
+
expect([1, 2, 3].first).toBe(1);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('last returns the last element of the array', () => {
|
|
17
|
+
expect([1, 2, 3].last).toBe(3);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('isObject checks if a value is an object', () => {
|
|
21
|
+
expect(Object.isObject({})).toBe(true);
|
|
22
|
+
expect(Object.isObject(123)).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('isAsync identifies async functions', () => {
|
|
26
|
+
async function asyncFunc() {}
|
|
27
|
+
expect(Function.isAsync(asyncFunc)).toBe(true);
|
|
28
|
+
expect(Function.isAsync(() => {})).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('hasAll checks if an object has all specified keys', () => {
|
|
32
|
+
const obj = { a: 1, b: 2 };
|
|
33
|
+
expect(Reflect.hasAll(obj, 'a', 'b')).toBe(true);
|
|
34
|
+
expect(Reflect.hasAll(obj, 'a', 'c')).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"allowSyntheticDefaultImports": true,
|
|
5
|
+
"baseUrl": "src",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"inlineSourceMap": false,
|
|
9
|
+
"lib": ["esnext"],
|
|
10
|
+
"listEmittedFiles": false,
|
|
11
|
+
"listFiles": false,
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"noFallthroughCasesInSwitch": false,
|
|
14
|
+
"pretty": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"rootDir": "src",
|
|
17
|
+
"skipLibCheck": true,
|
|
18
|
+
"strict": true,
|
|
19
|
+
"traceResolution": false,
|
|
20
|
+
"types": ["node", "jest"]
|
|
21
|
+
},
|
|
22
|
+
"compileOnSave": false,
|
|
23
|
+
"exclude": ["node_modules", "dist"],
|
|
24
|
+
"include": ["src"]
|
|
25
|
+
}
|