@oscarpalmer/atoms 0.180.0 → 0.181.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.
@@ -10,12 +10,13 @@ type Parameters = {
10
10
  key?: unknown;
11
11
  value?: unknown;
12
12
  };
13
- declare function findValue(type: FindValueType, array: unknown[], parameters: unknown[], reversed: boolean): unknown;
13
+ declare function findValue(type: Exclude<FindValueType, 'item'>, array: unknown[], parameters: unknown[], reversed: boolean): number;
14
+ declare function findValue(type: Exclude<FindValueType, 'index'>, array: unknown[], parameters: unknown[], reversed: boolean): unknown;
14
15
  declare function findAbsoluteValueOrDefault(array: unknown[], parameters: unknown[], defaultValue: unknown, useDefaultValue: boolean, reversed: boolean): unknown;
15
16
  declare function findValues(type: FindValuesType, array: unknown[], parameters: unknown[], mapper?: unknown): FindValuesResult;
16
17
  declare function getFindParameters(original: unknown[]): Parameters;
17
- declare const FIND_VALUE_INDEX: FindValueType;
18
- declare const FIND_VALUE_ITEM: FindValueType;
18
+ declare const FIND_VALUE_INDEX = "index";
19
+ declare const FIND_VALUE_ITEM = "item";
19
20
  declare const FIND_VALUES_ALL: FindValuesType;
20
21
  declare const FIND_VALUES_UNIQUE: FindValuesType;
21
22
  //#endregion
@@ -5,9 +5,12 @@ function findValue(type, array, parameters, reversed) {
5
5
  if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
6
6
  const { bool, key, value } = getFindParameters(parameters);
7
7
  const callbacks = getArrayCallbacks(bool, key);
8
- if (callbacks?.bool == null && callbacks?.keyed == null) return findIndex ? array.indexOf(value) : array.find((item) => Object.is(item, value));
8
+ if (callbacks?.bool == null && callbacks?.keyed == null) {
9
+ if (findIndex) return reversed ? array.lastIndexOf(value) : array.indexOf(value);
10
+ return reversed ? array.findLast((item) => Object.is(item, value)) : array.find((item) => Object.is(item, value));
11
+ }
9
12
  if (callbacks.bool != null) {
10
- const index = array.findIndex(callbacks.bool);
13
+ const index = reversed ? array.findLastIndex(callbacks.bool) : array.findIndex(callbacks.bool);
11
14
  return findIndex ? index : array[index];
12
15
  }
13
16
  return findValueInArray(array, callbacks.keyed, value, findIndex, reversed);
@@ -31,5 +31,46 @@ declare function indexOf<Item>(array: Item[], filter: (item: Item, index: number
31
31
  * @returns Index of the first matching item, or `-1` if no match is found
32
32
  */
33
33
  declare function indexOf<Item>(array: Item[], item: Item): number;
34
+ declare namespace indexOf {
35
+ var last: typeof lastIndexOf;
36
+ }
37
+ /**
38
+ * Get the index of the last matching item by callback
39
+ *
40
+ * Available as `lastIndexOf` and `indexOf.last`
41
+ * @param array Array to search in
42
+ * @param callback Callback to get an item's value
43
+ * @param value Value to match against
44
+ * @returns Index of the last matching item, or `-1` if no match is found
45
+ */
46
+ declare function lastIndexOf<Item, Callback extends (item: Item, index: number, array: Item[]) => unknown>(array: Item[], callback: Callback, value: ReturnType<Callback>): number;
47
+ /**
48
+ * Get the index of the last matching item by key
49
+ *
50
+ * Available as `lastIndexOf` and `indexOf.last`
51
+ * @param array Array to search in
52
+ * @param key Key to match items by
53
+ * @param value Value to match against
54
+ * @returns Index of the last matching item, or `-1` if no match is found
55
+ */
56
+ declare function lastIndexOf<Item extends PlainObject, ItemKey extends keyof Item>(array: Item[], key: ItemKey, value: Item[ItemKey]): number;
57
+ /**
58
+ * Get the index of the last item matching the filter
59
+ *
60
+ * Available as `lastIndexOf` and `indexOf.last`
61
+ * @param array Array to search in
62
+ * @param filter Filter callback to match items
63
+ * @returns Index of the last matching item, or `-1` if no match is found
64
+ */
65
+ declare function lastIndexOf<Item>(array: Item[], filter: (item: Item, index: number, array: Item[]) => boolean): number;
66
+ /**
67
+ * Get the index of the last item matching the given item
68
+ *
69
+ * Available as `lastIndexOf` and `indexOf.last`
70
+ * @param array Array to search in
71
+ * @param item Item to match against
72
+ * @returns Index of the last matching item, or `-1` if no match is found
73
+ */
74
+ declare function lastIndexOf<Item>(array: Item[], item: Item): number;
34
75
  //#endregion
35
- export { indexOf };
76
+ export { indexOf, lastIndexOf };
@@ -3,5 +3,9 @@ import { FIND_VALUE_INDEX, findValue } from "./find.mjs";
3
3
  function indexOf(array, ...parameters) {
4
4
  return findValue(FIND_VALUE_INDEX, array, parameters, false);
5
5
  }
6
+ indexOf.last = lastIndexOf;
7
+ function lastIndexOf(array, ...parameters) {
8
+ return findValue(FIND_VALUE_INDEX, array, parameters, true);
9
+ }
6
10
  //#endregion
7
- export { indexOf };
11
+ export { indexOf, lastIndexOf };
@@ -1,4 +1,4 @@
1
- import { isNumber } from "../is.mjs";
1
+ import { isNonNumber } from "../is.mjs";
2
2
  //#region src/internal/math/aggregate.ts
3
3
  function aggregate(type, array, key) {
4
4
  const length = Array.isArray(array) ? array.length : 0;
@@ -14,7 +14,7 @@ function aggregate(type, array, key) {
14
14
  for (let index = 0; index < length; index += 1) {
15
15
  const item = array[index];
16
16
  const value = callback == null ? item : callback(item, index, array);
17
- if (!isNumber(value)) continue;
17
+ if (isNonNumber(value)) continue;
18
18
  aggregated = aggregator(aggregated, value, notNumber);
19
19
  counted += 1;
20
20
  notNumber = false;
@@ -1,7 +1,7 @@
1
- import { isPlainObject } from "./is.mjs";
1
+ import { isNonPlainObject } from "./is.mjs";
2
2
  //#region src/internal/result.ts
3
3
  function _isResult(value, okValue) {
4
- if (!isPlainObject(value)) return false;
4
+ if (isNonPlainObject(value)) return false;
5
5
  return value.ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value;
6
6
  }
7
7
  function isError(value, extended) {
@@ -7,12 +7,14 @@
7
7
  declare function getString(value: unknown): string;
8
8
  declare function ignoreKey(key: string): boolean;
9
9
  /**
10
- * Join an array of values into a string
11
- * @param value Array of values
10
+ * Join an array of values into a string _(while ignoring empty values)_
11
+ *
12
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
13
+ * @param array Array of values
12
14
  * @param delimiter Delimiter to use between values
13
15
  * @returns Joined string
14
16
  */
15
- declare function join(value: unknown[], delimiter?: string): string;
17
+ declare function join(array: unknown[], delimiter?: string): string;
16
18
  declare function tryDecode(value: string): string;
17
19
  declare function tryEncode(value: boolean | number | string): unknown;
18
20
  /**
@@ -1,4 +1,3 @@
1
- import { compact } from "./array/compact.mjs";
2
1
  //#region src/internal/string.ts
3
2
  /**
4
3
  * Get the string value from any value
@@ -17,13 +16,23 @@ function ignoreKey(key) {
17
16
  return EXPRESSION_IGNORED.test(key);
18
17
  }
19
18
  /**
20
- * Join an array of values into a string
21
- * @param value Array of values
19
+ * Join an array of values into a string _(while ignoring empty values)_
20
+ *
21
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
22
+ * @param array Array of values
22
23
  * @param delimiter Delimiter to use between values
23
24
  * @returns Joined string
24
25
  */
25
- function join(value, delimiter) {
26
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
26
+ function join(array, delimiter) {
27
+ if (!Array.isArray(array)) return "";
28
+ const { length } = array;
29
+ if (length === 0) return "";
30
+ const values = [];
31
+ for (let index = 0; index < length; index += 1) {
32
+ const item = getString(array[index]);
33
+ if (item.trim().length > 0) values.push(item);
34
+ }
35
+ return values.join(typeof delimiter === "string" ? delimiter : "");
27
36
  }
28
37
  function tryCallback(value, callback) {
29
38
  try {
@@ -1,4 +1,4 @@
1
- import { isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
1
+ import { isNonPlainObject, isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
2
2
  import { getCompareHandlers } from "./handlers.mjs";
3
3
  //#region src/internal/value/equal.ts
4
4
  /**
@@ -131,7 +131,7 @@ function getEqualOptions(input) {
131
131
  options.ignoreCase = input;
132
132
  return options;
133
133
  }
134
- if (!isPlainObject(input)) return options;
134
+ if (isNonPlainObject(input)) return options;
135
135
  options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
136
136
  options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
137
137
  options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
@@ -1,4 +1,4 @@
1
- import { isConstructor } from "../is.mjs";
1
+ import { isNonConstructor } from "../is.mjs";
2
2
  //#region src/internal/value/handlers.ts
3
3
  function getCompareHandlers(owner, options) {
4
4
  const handlers = getHandlers(owner, options);
@@ -26,7 +26,7 @@ function getHandlers(owner, options) {
26
26
  if (isConstructable(first) && isConstructable(second) && first.constructor === second.constructor) return handlers.get(first.constructor);
27
27
  },
28
28
  register(constructor, handler) {
29
- if (!isConstructor(constructor) || handler === owner) return;
29
+ if (isNonConstructor(constructor) || handler === owner) return;
30
30
  let actual = handler ?? options.method;
31
31
  if (typeof actual !== "function" && typeof actual !== "string") return;
32
32
  if (typeof actual === "string") actual = typeof constructor.prototype[actual] === "function" ? actual : void 0;
@@ -1,5 +1,6 @@
1
1
  import { omit } from "./omit.mjs";
2
2
  import { pick } from "./pick.mjs";
3
+ import { Shaken, shake } from "./shake.mjs";
3
4
  import { Smushed, smush } from "./smush.mjs";
4
5
  import { Unsmushed, unsmush } from "./unsmush.mjs";
5
- export { type Smushed, type Unsmushed, omit, pick, smush, unsmush };
6
+ export { type Shaken, type Smushed, type Unsmushed, omit, pick, shake, smush, unsmush };
@@ -1,5 +1,6 @@
1
1
  import { omit } from "./omit.mjs";
2
2
  import { pick } from "./pick.mjs";
3
+ import { shake } from "./shake.mjs";
3
4
  import { smush } from "./smush.mjs";
4
5
  import { unsmush } from "./unsmush.mjs";
5
- export { omit, pick, smush, unsmush };
6
+ export { omit, pick, shake, smush, unsmush };
@@ -5,16 +5,29 @@ import { ArrayOrPlainObject, NestedPartial } from "../models.mjs";
5
5
  * Options for merging values
6
6
  */
7
7
  type MergeOptions = {
8
+ /**
9
+ * Assign values to the first array or object instead of creating a new one?
10
+ */
11
+ assignValues?: boolean;
8
12
  /**
9
13
  * Key _(or key epxressions)_ for values that should be replaced
14
+ *
10
15
  * ```ts
11
16
  * merge([{items: [1, 2, 3]}, {items: [99]}]); // {items: [99]}
12
17
  * ```
13
18
  */
14
19
  replaceableObjects?: string | RegExp | Array<string | RegExp>;
20
+ /**
21
+ * Skip nullable values when merging objects?
22
+ *
23
+ * ```ts
24
+ * merge({a: 1, b: 2}, {b: null, c: 3}, {d: null}); // {a: 1, b: 2, c: 3}
25
+ * ```
26
+ */
15
27
  skipNullableAny?: boolean;
16
28
  /**
17
29
  * Skip nullable values when merging arrays?
30
+ *
18
31
  * ```ts
19
32
  * merge([1, 2, 3], [null, null, 99]); // [1, 2, 99]
20
33
  * ```
@@ -3,12 +3,14 @@ import { join } from "../internal/string.mjs";
3
3
  //#region src/value/merge.ts
4
4
  function getMergeOptions(options) {
5
5
  const actual = {
6
+ assignValues: false,
6
7
  replaceableObjects: void 0,
7
8
  skipNullableAny: false,
8
9
  skipNullableInArrays: false
9
10
  };
10
11
  if (typeof options !== "object" || options == null) return actual;
11
12
  actual.replaceableObjects = getReplaceableObjects(options.replaceableObjects);
13
+ actual.assignValues = options.assignValues === true;
12
14
  actual.skipNullableAny = options.skipNullableAny === true;
13
15
  actual.skipNullableInArrays = options.skipNullableInArrays === true;
14
16
  return actual;
@@ -38,7 +40,7 @@ merge.initialize = initializeMerger;
38
40
  function mergeObjects(values, options, prefix) {
39
41
  const { length } = values;
40
42
  const isArray = values.every(Array.isArray);
41
- const merged = isArray ? [] : {};
43
+ const merged = options.assignValues ? values[0] : isArray ? [] : {};
42
44
  for (let outerIndex = 0; outerIndex < length; outerIndex += 1) {
43
45
  const item = values[outerIndex];
44
46
  const keys = Object.keys(item);
@@ -0,0 +1,7 @@
1
+ import { PlainObject } from "../models.mjs";
2
+
3
+ //#region src/value/shake.d.ts
4
+ type Shaken<Value extends PlainObject> = { [Key in keyof Value]: Value[Key] extends undefined ? never : Value[Key] };
5
+ declare function shake<Value extends PlainObject>(value: Value): Shaken<Value>;
6
+ //#endregion
7
+ export { Shaken, shake };
@@ -0,0 +1,16 @@
1
+ import { isNonPlainObject } from "../internal/is.mjs";
2
+ //#region src/value/shake.ts
3
+ function shake(value) {
4
+ const shaken = {};
5
+ if (isNonPlainObject(value)) return shaken;
6
+ const keys = Object.keys(value);
7
+ const { length } = keys;
8
+ for (let index = 0; index < length; index += 1) {
9
+ const key = keys[index];
10
+ const val = value[key];
11
+ if (val !== void 0) shaken[key] = val;
12
+ }
13
+ return shaken;
14
+ }
15
+ //#endregion
16
+ export { shake };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.180.0",
3
+ "version": "0.181.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "helper",
@@ -52,7 +52,7 @@ export function exists(array: unknown[], ...parameters: unknown[]): boolean {
52
52
  return Array.isArray(array) ? array.includes(parameters[0]) : false;
53
53
  }
54
54
 
55
- return (findValue(FIND_VALUE_INDEX, array, parameters, false) as number) > -1;
55
+ return findValue(FIND_VALUE_INDEX, array, parameters, false) > -1;
56
56
  }
57
57
 
58
58
  // #endregion
package/src/array/find.ts CHANGED
@@ -52,4 +52,62 @@ export function find(array: unknown[], ...parameters: unknown[]): unknown {
52
52
  return findValue(FIND_VALUE_ITEM, array, parameters, false);
53
53
  }
54
54
 
55
+ find.last = findLast;
56
+
57
+ /**
58
+ * Get the last item matching the given value
59
+ *
60
+ * Available as `findLast` and `find.last`
61
+ * @param array Array to search in
62
+ * @param callback Callback to get an item's value for matching
63
+ * @param value Value to match against
64
+ * @returns Last item that matches the value, or `undefined` if no match is found
65
+ */
66
+ export function findLast<
67
+ Item,
68
+ Callback extends (item: Item, index: number, array: Item[]) => unknown,
69
+ >(array: Item[], callback: Callback, value: ReturnType<Callback>): Item | undefined;
70
+
71
+ /**
72
+ * Get the last item matching the given value by key
73
+ *
74
+ * Available as `findLast` and `find.last`
75
+ * @param array Array to search in
76
+ * @param key Key to get an item's value for matching
77
+ * @param value Value to match against
78
+ * @returns Last item that matches the value, or `undefined` if no match is found
79
+ */
80
+ export function findLast<Item extends PlainObject, ItemKey extends keyof Item>(
81
+ array: Item[],
82
+ key: ItemKey,
83
+ value: Item[ItemKey],
84
+ ): Item | undefined;
85
+
86
+ /**
87
+ * Get the last item matching the filter
88
+ *
89
+ * Available as `findLast` and `find.last`
90
+ * @param array Array to search in
91
+ * @param filter Filter callback to match items
92
+ * @returns Last item that matches the filter, or `undefined` if no match is found
93
+ */
94
+ export function findLast<Item>(
95
+ array: Item[],
96
+ filter: (item: Item, index: number, array: Item[]) => boolean,
97
+ ): Item | undefined;
98
+
99
+ /**
100
+ * Get the last item matching the given value
101
+ *
102
+ * Available as `findLast` and `find.last`
103
+ * @param array Array to search in
104
+ * @param value Value to match against
105
+ * @returns Last item that matches the value, or `undefined` if no match is found
106
+ */
107
+ export function findLast<Item>(array: Item[], value: Item): Item | undefined;
108
+
109
+ export function findLast(array: unknown[], ...parameters: unknown[]): unknown {
110
+ return findValue(FIND_VALUE_ITEM, array, parameters, true);
111
+ }
112
+
55
113
  // #endregion
package/src/array/get.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {isPlainObject} from '../internal/is';
1
+ import {isNonPlainObject} from '../internal/is';
2
2
  import type {NumericalKeys, PlainObject} from '../models';
3
3
 
4
4
  // #region Functions
@@ -50,7 +50,7 @@ export function getArray(value: unknown, indiced?: unknown): unknown[] {
50
50
  return [...value.values()];
51
51
  }
52
52
 
53
- if (!isPlainObject(value)) {
53
+ if (isNonPlainObject(value)) {
54
54
  return [value];
55
55
  }
56
56
 
@@ -21,6 +21,20 @@ type Parameters = {
21
21
 
22
22
  // #region Functions
23
23
 
24
+ export function findValue(
25
+ type: Exclude<FindValueType, 'item'>,
26
+ array: unknown[],
27
+ parameters: unknown[],
28
+ reversed: boolean,
29
+ ): number;
30
+
31
+ export function findValue(
32
+ type: Exclude<FindValueType, 'index'>,
33
+ array: unknown[],
34
+ parameters: unknown[],
35
+ reversed: boolean,
36
+ ): unknown;
37
+
24
38
  export function findValue(
25
39
  type: FindValueType,
26
40
  array: unknown[],
@@ -38,11 +52,17 @@ export function findValue(
38
52
  const callbacks = getArrayCallbacks(bool, key);
39
53
 
40
54
  if (callbacks?.bool == null && callbacks?.keyed == null) {
41
- return findIndex ? array.indexOf(value) : array.find(item => Object.is(item, value));
55
+ if (findIndex) {
56
+ return reversed ? array.lastIndexOf(value) : array.indexOf(value);
57
+ }
58
+
59
+ return reversed
60
+ ? array.findLast(item => Object.is(item, value))
61
+ : array.find(item => Object.is(item, value));
42
62
  }
43
63
 
44
64
  if (callbacks.bool != null) {
45
- const index = array.findIndex(callbacks.bool);
65
+ const index = reversed ? array.findLastIndex(callbacks.bool) : array.findIndex(callbacks.bool);
46
66
 
47
67
  return findIndex ? index : array[index];
48
68
  }
@@ -167,9 +187,9 @@ export function getFindParameters(original: unknown[]): Parameters {
167
187
 
168
188
  // #region Variables
169
189
 
170
- export const FIND_VALUE_INDEX: FindValueType = 'index';
190
+ export const FIND_VALUE_INDEX = 'index';
171
191
 
172
- export const FIND_VALUE_ITEM: FindValueType = 'item';
192
+ export const FIND_VALUE_ITEM = 'item';
173
193
 
174
194
  export const FIND_VALUES_ALL: FindValuesType = 'all';
175
195
 
@@ -48,7 +48,65 @@ export function indexOf<Item>(
48
48
  export function indexOf<Item>(array: Item[], item: Item): number;
49
49
 
50
50
  export function indexOf(array: unknown[], ...parameters: unknown[]): number {
51
- return findValue(FIND_VALUE_INDEX, array, parameters, false) as number;
51
+ return findValue(FIND_VALUE_INDEX, array, parameters, false);
52
+ }
53
+
54
+ indexOf.last = lastIndexOf;
55
+
56
+ /**
57
+ * Get the index of the last matching item by callback
58
+ *
59
+ * Available as `lastIndexOf` and `indexOf.last`
60
+ * @param array Array to search in
61
+ * @param callback Callback to get an item's value
62
+ * @param value Value to match against
63
+ * @returns Index of the last matching item, or `-1` if no match is found
64
+ */
65
+ export function lastIndexOf<
66
+ Item,
67
+ Callback extends (item: Item, index: number, array: Item[]) => unknown,
68
+ >(array: Item[], callback: Callback, value: ReturnType<Callback>): number;
69
+
70
+ /**
71
+ * Get the index of the last matching item by key
72
+ *
73
+ * Available as `lastIndexOf` and `indexOf.last`
74
+ * @param array Array to search in
75
+ * @param key Key to match items by
76
+ * @param value Value to match against
77
+ * @returns Index of the last matching item, or `-1` if no match is found
78
+ */
79
+ export function lastIndexOf<Item extends PlainObject, ItemKey extends keyof Item>(
80
+ array: Item[],
81
+ key: ItemKey,
82
+ value: Item[ItemKey],
83
+ ): number;
84
+
85
+ /**
86
+ * Get the index of the last item matching the filter
87
+ *
88
+ * Available as `lastIndexOf` and `indexOf.last`
89
+ * @param array Array to search in
90
+ * @param filter Filter callback to match items
91
+ * @returns Index of the last matching item, or `-1` if no match is found
92
+ */
93
+ export function lastIndexOf<Item>(
94
+ array: Item[],
95
+ filter: (item: Item, index: number, array: Item[]) => boolean,
96
+ ): number;
97
+
98
+ /**
99
+ * Get the index of the last item matching the given item
100
+ *
101
+ * Available as `lastIndexOf` and `indexOf.last`
102
+ * @param array Array to search in
103
+ * @param item Item to match against
104
+ * @returns Index of the last matching item, or `-1` if no match is found
105
+ */
106
+ export function lastIndexOf<Item>(array: Item[], item: Item): number;
107
+
108
+ export function lastIndexOf(array: unknown[], ...parameters: unknown[]): number {
109
+ return findValue(FIND_VALUE_INDEX, array, parameters, true);
52
110
  }
53
111
 
54
112
  // #endregion
@@ -1,5 +1,5 @@
1
1
  import type {NumericalValues, PlainObject} from '../../models';
2
- import {isNumber} from '../is';
2
+ import {isNonNumber} from '../is';
3
3
 
4
4
  // #region Types
5
5
 
@@ -40,7 +40,7 @@ export function aggregate(type: AggregationType, array: unknown[], key: unknown)
40
40
 
41
41
  const value = callback == null ? item : callback(item as never, index, array);
42
42
 
43
- if (!isNumber(value)) {
43
+ if (isNonNumber(value)) {
44
44
  continue;
45
45
  }
46
46
 
@@ -1,14 +1,17 @@
1
+ import type {PlainObject} from '../models';
1
2
  import type {Err, ExtendedErr, Ok, Result} from '../result/models';
2
- import {isPlainObject} from './is';
3
+ import {isNonPlainObject} from './is';
3
4
 
4
5
  // #region Functions
5
6
 
6
7
  function _isResult(value: unknown, okValue: boolean): value is Result<unknown, unknown> {
7
- if (!isPlainObject(value)) {
8
+ if (isNonPlainObject(value)) {
8
9
  return false;
9
10
  }
10
11
 
11
- return value.ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value;
12
+ return (
13
+ (value as PlainObject).ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value
14
+ );
12
15
  }
13
16
 
14
17
  /**
@@ -1,5 +1,3 @@
1
- import {compact} from './array/compact';
2
-
3
1
  // #region Functions
4
2
 
5
3
  /**
@@ -36,15 +34,35 @@ export function ignoreKey(key: string): boolean {
36
34
  }
37
35
 
38
36
  /**
39
- * Join an array of values into a string
40
- * @param value Array of values
37
+ * Join an array of values into a string _(while ignoring empty values)_
38
+ *
39
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
40
+ * @param array Array of values
41
41
  * @param delimiter Delimiter to use between values
42
42
  * @returns Joined string
43
43
  */
44
- export function join(value: unknown[], delimiter?: string): string {
45
- return compact(value)
46
- .map(getString)
47
- .join(typeof delimiter === 'string' ? delimiter : '');
44
+ export function join(array: unknown[], delimiter?: string): string {
45
+ if (!Array.isArray(array)) {
46
+ return '';
47
+ }
48
+
49
+ const {length} = array;
50
+
51
+ if (length === 0) {
52
+ return '';
53
+ }
54
+
55
+ const values: string[] = [];
56
+
57
+ for (let index = 0; index < length; index += 1) {
58
+ const item = getString(array[index]);
59
+
60
+ if (item.trim().length > 0) {
61
+ values.push(item);
62
+ }
63
+ }
64
+
65
+ return values.join(typeof delimiter === 'string' ? delimiter : '');
48
66
  }
49
67
 
50
68
  function tryCallback<T, U>(value: T, callback: (value: T) => U): U {
@@ -1,5 +1,5 @@
1
1
  import type {ArrayOrPlainObject, Constructor, PlainObject, TypedArray} from '../../models';
2
- import {isPlainObject, isPrimitive, isTypedArray} from '../is';
2
+ import {isNonPlainObject, isPlainObject, isPrimitive, isTypedArray} from '../is';
3
3
  import {getCompareHandlers} from './handlers';
4
4
 
5
5
  // #region Types
@@ -377,7 +377,7 @@ function getEqualOptions(input?: boolean | EqualOptions): Options {
377
377
  return options;
378
378
  }
379
379
 
380
- if (!isPlainObject(input)) {
380
+ if (isNonPlainObject(input)) {
381
381
  return options;
382
382
  }
383
383
 
@@ -1,5 +1,5 @@
1
1
  import type {Constructor, GenericCallback} from '../../models';
2
- import {isConstructor} from '../is';
2
+ import {isNonConstructor} from '../is';
3
3
 
4
4
  type Options = {
5
5
  callback: GenericCallback;
@@ -47,7 +47,7 @@ function getHandlers(owner: GenericCallback, options: Options) {
47
47
  }
48
48
  },
49
49
  register(constructor: Constructor, handler?: string | GenericCallback) {
50
- if (!isConstructor(constructor) || handler === owner) {
50
+ if (isNonConstructor(constructor) || handler === owner) {
51
51
  return;
52
52
  }
53
53
 
@@ -1,4 +1,5 @@
1
1
  export {omit} from './omit';
2
2
  export {pick} from './pick';
3
+ export {shake, type Shaken} from './shake';
3
4
  export {smush, type Smushed} from './smush';
4
5
  export {unsmush, type Unsmushed} from './unsmush';