@oscarpalmer/atoms 0.166.3 → 0.168.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.166.3",
3
+ "version": "0.168.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "helper",
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/array/move.d.mts",
45
45
  "default": "./dist/array/move.mjs"
46
46
  },
47
+ "./array/sort": {
48
+ "types": "./dist/array/sort.d.mts",
49
+ "default": "./dist/array/sort.mjs"
50
+ },
47
51
  "./array/swap": {
48
52
  "types": "./dist/array/swap.d.mts",
49
53
  "default": "./dist/array/swap.mjs"
@@ -111,10 +115,18 @@
111
115
  "types": "./dist/promise/delay.d.mts",
112
116
  "default": "./dist/promise/delay.mjs"
113
117
  },
118
+ "./promise/misc": {
119
+ "types": "./dist/promise/misc.d.mts",
120
+ "default": "./dist/promise/misc.mjs"
121
+ },
114
122
  "./promise/models": {
115
123
  "types": "./dist/promise/models.d.mts",
116
124
  "default": "./dist/promise/models.mjs"
117
125
  },
126
+ "./promise/timed": {
127
+ "types": "./dist/promise/timed.d.mts",
128
+ "default": "./dist/promise/timed.mjs"
129
+ },
118
130
  "./query": {
119
131
  "types": "./dist/query.d.mts",
120
132
  "default": "./dist/query.mjs"
@@ -131,6 +143,26 @@
131
143
  "types": "./dist/result/index.d.mts",
132
144
  "default": "./dist/result/index.mjs"
133
145
  },
146
+ "./result/flow": {
147
+ "types": "./dist/result/work/flow.d.mts",
148
+ "default": "./dist/result/work/flow.mjs"
149
+ },
150
+ "./result/match": {
151
+ "types": "./dist/result/match.d.mts",
152
+ "default": "./dist/result/match.mjs"
153
+ },
154
+ "./result/misc": {
155
+ "types": "./dist/result/misc.d.mts",
156
+ "default": "./dist/result/misc.mjs"
157
+ },
158
+ "./result/models": {
159
+ "types": "./dist/result/models.d.mts",
160
+ "default": "./dist/result/models.mjs"
161
+ },
162
+ "./result/pipe": {
163
+ "types": "./dist/result/work/pipe.d.mts",
164
+ "default": "./dist/result/work/pipe.mjs"
165
+ },
134
166
  "./sized/map": {
135
167
  "types": "./dist/sized/map.d.mts",
136
168
  "default": "./dist/sized/map.mjs"
@@ -203,4 +235,4 @@
203
235
  "vitest": "npm:@voidzero-dev/vite-plus-test@latest"
204
236
  },
205
237
  "packageManager": "npm@11.11.1"
206
- }
238
+ }
@@ -16,7 +16,6 @@ export * from './position';
16
16
  export * from './push';
17
17
  export * from './select';
18
18
  export * from './slice';
19
- export * from './sort';
20
19
  export * from './splice';
21
20
  export * from './to-set';
22
21
  export * from './toggle';
package/src/array/sort.ts CHANGED
@@ -43,6 +43,18 @@ type ArrayKeySorters<Item extends PlainObject> = {
43
43
  [ItemKey in keyof Item]: ArrayKeySorter<Item, ItemKey>;
44
44
  }[keyof Item];
45
45
 
46
+ /**
47
+ * Sorter to use for sorting
48
+ */
49
+ type ArraySorter<Item> = Item extends PlainObject
50
+ ?
51
+ | keyof Item
52
+ | ArrayComparisonSorter<Item>
53
+ | ArrayKeySorters<Item>
54
+ | ArrayValueSorter<Item>
55
+ | ComparisonSorter<Item>
56
+ : ArrayComparisonSorter<Item> | ArrayValueSorter<Item> | ComparisonSorter<Item>;
57
+
46
58
  /**
47
59
  * Sorting information for arrays _(using a value callback and built-in comparison)_
48
60
  */
@@ -74,41 +86,25 @@ type CompareCallbackValue<Item> = Item extends Primitive ? Item : unknown;
74
86
  */
75
87
  type ComparisonSorter<Item> = (first: Item, second: Item) => number;
76
88
 
77
- /**
78
- * Internal sorter information
79
- */
80
89
  type InternalSorter = {
81
- compare?: SorterCompare;
90
+ compare?: InternalSorterCompare;
82
91
  get: boolean;
83
92
  identifier: string;
84
93
  modifier: number;
85
- value?: (item: PlainObject) => unknown;
94
+ value?: Function;
86
95
  };
87
96
 
88
- /**
89
- * Direction to sort by
90
- */
91
- export type SortDirection = 'ascending' | 'descending';
92
-
93
- /**
94
- * Comparison callbacks for sorter
95
- */
96
- type SorterCompare = {
97
+ type InternalSorterCompare = {
97
98
  complex?: Function;
98
99
  simple?: Function;
99
100
  };
100
101
 
101
102
  /**
102
- * Sorter to use for sorting
103
+ * Direction to sort by
103
104
  */
104
- type Sorter<Item> = Item extends PlainObject
105
- ?
106
- | keyof Item
107
- | ArrayComparisonSorter<Item>
108
- | ArrayKeySorters<Item>
109
- | ArrayValueSorter<Item>
110
- | ComparisonSorter<Item>
111
- : ArrayComparisonSorter<Item> | ArrayValueSorter<Item> | ComparisonSorter<Item>;
105
+ export type SortDirection = 'ascending' | 'descending';
106
+
107
+ export type Sorter<Item> = (array: Item[]) => Item[];
112
108
 
113
109
  // #endregion
114
110
 
@@ -125,6 +121,13 @@ function getComparisonSorter(callback: Function, modifier: number): InternalSort
125
121
  };
126
122
  }
127
123
 
124
+ function getModifier(first: unknown, second: unknown): number {
125
+ const direction =
126
+ first === true || second === true ? SORT_DIRECTION_DESCENDING : SORT_DIRECTION_ASCENDING;
127
+
128
+ return modifiers[direction];
129
+ }
130
+
128
131
  function getObjectSorter(obj: PlainObject, modifier: number): InternalSorter | undefined {
129
132
  let sorter: InternalSorter | undefined;
130
133
 
@@ -165,18 +168,70 @@ function getSorter(value: unknown, modifier: number): InternalSorter | undefined
165
168
  }
166
169
  }
167
170
 
171
+ function getSorters(value: unknown, modifier: number): InternalSorter[] {
172
+ const array = Array.isArray(value) ? value : [value];
173
+ const {length} = array;
174
+
175
+ const sorters: InternalSorter[] = [];
176
+
177
+ for (let index = 0; index < length; index += 1) {
178
+ const item = array[index];
179
+
180
+ const sorter = getSorter(item, modifier);
181
+
182
+ if (sorter != null) {
183
+ sorters.push(sorter);
184
+ }
185
+ }
186
+
187
+ return sorters.filter(
188
+ (value, index, array) =>
189
+ array.findIndex(next => next.identifier === value.identifier) === index,
190
+ );
191
+ }
192
+
168
193
  function getValueSorter(value: string | Function, modifier: number): InternalSorter {
169
194
  return {
170
195
  modifier,
171
196
  get: true,
172
197
  identifier: String(value),
173
- value:
174
- typeof value === 'function'
175
- ? (value as (item: PlainObject) => unknown)
176
- : item => (item as PlainObject)[value],
198
+ value: typeof value === 'function' ? value : (item: unknown) => (item as PlainObject)[value],
177
199
  };
178
200
  }
179
201
 
202
+ /**
203
+ * Initialize a sort handler with sorters _(and an optional default direction)_
204
+ * @param sorters Sorters to use for sorting
205
+ * @param descending Sort in descending order? _(defaults to `false`; overridden by individual sorters)_
206
+ * @returns Sort handler
207
+ */
208
+ function initializeSort<Item>(
209
+ sorters: Array<ArraySorter<Item>>,
210
+ descending?: boolean,
211
+ ): Sorter<Item>;
212
+
213
+ /**
214
+ * Initialize a sort handler with a sorter _(and an optional default direction)_
215
+ * @param sorter Sorter to use for sorting
216
+ * @param descending Sort in descending order? _(defaults to `false`; overridden by individual sorters)_
217
+ * @returns Sort handler
218
+ */
219
+ function initializeSort<Item>(sorter: ArraySorter<Item>, descending?: boolean): Sorter<Item>;
220
+
221
+ /**
222
+ * Initialize a sort handler _(with an optional default direction)_
223
+ * @param descending Sort in descending order? _(defaults to `false`)_
224
+ * @returns Sort handler
225
+ */
226
+ function initializeSort<Item>(descending?: boolean): Sorter<Item>;
227
+
228
+ function initializeSort(first?: unknown, second?: unknown): Sorter<unknown> {
229
+ const modifier = getModifier(first, second);
230
+ const sorters = getSorters(first, modifier);
231
+
232
+ return array => work(array, sorters, modifier);
233
+ }
234
+
180
235
  /**
181
236
  * Sort an array of items, using multiple sorters to sort by specific values
182
237
  * @param array Array to sort
@@ -186,7 +241,7 @@ function getValueSorter(value: string | Function, modifier: number): InternalSor
186
241
  */
187
242
  export function sort<Item>(
188
243
  array: Item[],
189
- sorters: Array<Sorter<Item>>,
244
+ sorters: Array<ArraySorter<Item>>,
190
245
  descending?: boolean,
191
246
  ): Item[];
192
247
 
@@ -197,7 +252,7 @@ export function sort<Item>(
197
252
  * @param descending Sort in descending order? _(defaults to `false`; overridden by individual sorters)_
198
253
  * @returns Sorted array
199
254
  */
200
- export function sort<Item>(array: Item[], sorter: Sorter<Item>, descending?: boolean): Item[];
255
+ export function sort<Item>(array: Item[], sorter: ArraySorter<Item>, descending?: boolean): Item[];
201
256
 
202
257
  /**
203
258
  * Sort an array of items
@@ -208,6 +263,12 @@ export function sort<Item>(array: Item[], sorter: Sorter<Item>, descending?: boo
208
263
  export function sort<Item>(array: Item[], descending?: boolean): Item[];
209
264
 
210
265
  export function sort(array: unknown[], first?: unknown, second?: unknown): unknown[] {
266
+ const modifier = getModifier(first, second);
267
+
268
+ return work(array, getSorters(first, modifier), modifier);
269
+ }
270
+
271
+ function work(array: unknown[], sorters: InternalSorter[], modifier: number): unknown[] {
211
272
  if (!Array.isArray(array)) {
212
273
  return [];
213
274
  }
@@ -216,51 +277,25 @@ export function sort(array: unknown[], first?: unknown, second?: unknown): unkno
216
277
  return array;
217
278
  }
218
279
 
219
- const direction =
220
- first === true || second === true ? SORT_DIRECTION_DESCENDING : SORT_DIRECTION_ASCENDING;
221
-
222
- const modifier = modifiers[direction];
223
-
224
- const sorters = (Array.isArray(first) ? first : [first])
225
- .map(item => getSorter(item, modifier))
226
- .filter(sorter => sorter != null)
227
- .filter(
228
- (current, index, filtered) =>
229
- filtered.findIndex(next => next.identifier === current.identifier) === index,
230
- );
231
-
232
280
  const {length} = sorters;
233
281
 
234
282
  if (length === 0) {
235
283
  return array.sort((first, second) => compare(first, second) * modifier);
236
284
  }
237
285
 
238
- if (length === 1) {
239
- const sorter = sorters[0];
240
-
241
- return array.sort((firstItem, secondItem) => {
242
- const firstValue = sorter.get ? sorter.value!(firstItem as PlainObject) : firstItem;
243
- const secondValue = sorter.get ? sorter.value!(secondItem as PlainObject) : secondItem;
244
-
245
- return (
246
- (sorter.compare?.complex?.(firstItem, firstValue, secondItem, secondValue) ??
247
- sorter.compare?.simple?.(firstItem, secondItem) ??
248
- compare(firstValue, secondValue)) * sorter.modifier
249
- );
250
- });
251
- }
252
-
253
- return array.sort((firstItem, secondItem) => {
286
+ return array.sort((first, second) => {
254
287
  for (let index = 0; index < length; index += 1) {
255
288
  const sorter = sorters[index];
256
289
 
257
- const firstValue = sorter.value?.(firstItem as PlainObject) ?? firstItem;
258
- const secondValue = sorter.value?.(secondItem as PlainObject) ?? secondItem;
290
+ const values = [
291
+ sorter.get ? sorter.value!(first as PlainObject) : first,
292
+ sorter.get ? sorter.value!(second as PlainObject) : second,
293
+ ];
259
294
 
260
295
  const comparison =
261
- (sorter.compare?.complex?.(firstItem, firstValue, secondItem, secondValue) ??
262
- sorter.compare?.simple?.(firstItem, secondItem) ??
263
- compare(firstValue, secondValue)) * sorter.modifier;
296
+ (sorter.compare?.complex?.(first, values[0], second, values[1]) ??
297
+ sorter.compare?.simple?.(values[0], values[1]) ??
298
+ compare(values[0], values[1])) * sorter.modifier;
264
299
 
265
300
  if (comparison !== 0) {
266
301
  return comparison;
@@ -271,6 +306,8 @@ export function sort(array: unknown[], first?: unknown, second?: unknown): unkno
271
306
  });
272
307
  }
273
308
 
309
+ sort.initialize = initializeSort;
310
+
274
311
  // #endregion
275
312
 
276
313
  // #region Variables
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from './array/filter';
2
2
  export * from './array/group-by';
3
3
  export * from './array/index';
4
4
  export * from './array/move';
5
+ export * from './array/sort';
5
6
  export * from './array/swap';
6
7
  export * from './array/to-map';
7
8
  export * from './array/to-record';
@@ -38,10 +39,19 @@ export * from './logger';
38
39
  export * from './math';
39
40
  export * from './models';
40
41
  export * from './number';
42
+ export * from './promise/delay';
41
43
  export * from './promise/index';
44
+ export * from './promise/misc';
45
+ export * from './promise/models';
46
+ export * from './promise/timed';
42
47
  export * from './query';
43
48
  export * from './queue';
44
49
  export * from './random';
45
50
  export * from './result/index';
51
+ export * from './result/match';
52
+ export * from './result/misc';
53
+ export * from './result/models';
54
+ export * from './result/work/flow';
55
+ export * from './result/work/pipe';
46
56
  export * from './sized/map';
47
57
  export * from './sized/set';
@@ -283,25 +283,3 @@ async function resultPromises(
283
283
  }
284
284
 
285
285
  // #endregion
286
-
287
- // #region Exports
288
-
289
- export {toPromise as fromResult} from '../result/misc';
290
- export {delay} from './delay';
291
- export {isFulfilled, isRejected} from './helpers';
292
- export {cancelable, toResult} from './misc';
293
- export {
294
- CancelablePromise,
295
- PromiseTimeoutError,
296
- type FulfilledPromise,
297
- type PromiseOptions,
298
- type PromisesOptions,
299
- type PromisesResult,
300
- type PromiseStrategy,
301
- type PromisesValues as PromisesValue,
302
- type PromisesValue as PromisesValueItem,
303
- type RejectedPromise,
304
- } from './models';
305
- export {timed} from './timed';
306
-
307
- // #endregion
@@ -84,3 +84,10 @@ export async function toResult<Value>(
84
84
  }
85
85
 
86
86
  // #endregion
87
+
88
+ // #region Exports
89
+
90
+ export {toPromise as fromResult} from '../result/misc';
91
+ export {isFulfilled, isRejected} from './helpers';
92
+
93
+ // #endregion
@@ -95,12 +95,3 @@ attempt.pipe = attemptPipe;
95
95
  attempt.promise = attemptPromise;
96
96
 
97
97
  // #endregion
98
-
99
- // #region Exports
100
-
101
- export {isError, isOk, isResult} from '../internal/result';
102
- export {toResult as fromPromise} from '../promise/misc';
103
- export {error, ok, toPromise, unwrap} from './misc';
104
- export type {Err, ExtendedErr, ExtendedResult, Ok, Result} from './models';
105
-
106
- // #endregion
@@ -113,3 +113,9 @@ export function unwrap(value: unknown, defaultValue: unknown): unknown {
113
113
  const MESSAGE_PROMISE_RESULT = 'toPromise expected to receive a Result';
114
114
 
115
115
  // #endregion
116
+
117
+ // #region Exports
118
+
119
+ export {isError, isOk, isResult} from '../internal/result';
120
+
121
+ // #endregion