@oscarpalmer/atoms 0.156.0 → 0.158.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.
@@ -1,6 +1,7 @@
1
1
  import { noop } from "../internal/function/misc.js";
2
2
  import { TIMER_DEBOUNCE, TIMER_THROTTLE, getTimer } from "../internal/function/timer.js";
3
3
  import { memoize } from "./memoize.js";
4
+ import { once } from "./once.js";
4
5
  /**
5
6
  * Debounce a function, ensuring it is only called after `time` milliseconds have passed
6
7
  *
@@ -21,4 +22,4 @@ function debounce(callback, time) {
21
22
  function throttle(callback, time) {
22
23
  return getTimer(TIMER_THROTTLE, callback, time);
23
24
  }
24
- export { debounce, memoize, noop, throttle };
25
+ export { debounce, memoize, noop, once, throttle };
@@ -0,0 +1,97 @@
1
+ import { assert } from "./assert.js";
2
+ /**
3
+ * Create an asynchronous function that can only be called once, rejecting or resolving the same result on subsequent calls
4
+ * @param callback Callback to use once
5
+ * @returns Once callback
6
+ */
7
+ function asyncOnce(callback) {
8
+ assert(() => typeof callback === "function", MESSAGE_EXPECTATION);
9
+ const state = {
10
+ called: false,
11
+ cleared: false,
12
+ error: false,
13
+ finished: false,
14
+ items: [],
15
+ value: void 0
16
+ };
17
+ const fn = (...parameters) => {
18
+ if (state.cleared) return Promise.reject(new Error(MESSAGE_CLEARED));
19
+ if (state.finished) return state.error ? Promise.reject(state.value) : Promise.resolve(state.value);
20
+ if (state.called) return new Promise((resolve, reject) => {
21
+ state.items.push({
22
+ reject,
23
+ resolve
24
+ });
25
+ });
26
+ state.called = true;
27
+ return new Promise((resolve, reject) => {
28
+ state.items.push({
29
+ reject,
30
+ resolve
31
+ });
32
+ callback(...parameters).then((value) => {
33
+ handleResult(state, value, false);
34
+ }).catch((error) => {
35
+ handleResult(state, error, true);
36
+ });
37
+ });
38
+ };
39
+ Object.defineProperties(fn, {
40
+ called: { get: () => state.called },
41
+ cleared: { get: () => state.cleared },
42
+ error: { get: () => state.error },
43
+ finished: { get: () => state.finished }
44
+ });
45
+ fn.clear = () => {
46
+ if (!state.called || !state.finished || state.cleared) return;
47
+ state.cleared = true;
48
+ state.value = void 0;
49
+ };
50
+ return fn;
51
+ }
52
+ function handleResult(state, value, error) {
53
+ state.error = error;
54
+ state.finished = true;
55
+ state.value = value;
56
+ const items = state.items.splice(0);
57
+ const { length } = items;
58
+ for (let index = 0; index < length; index += 1) {
59
+ const { reject, resolve } = items[index];
60
+ if (error) reject(value);
61
+ else resolve(value);
62
+ }
63
+ }
64
+ /**
65
+ * Create a function that can only be called once, returning the same value on subsequent calls
66
+ * @param callback Callback to use once
67
+ * @returns Once callback
68
+ */
69
+ function once(callback) {
70
+ assert(() => typeof callback === "function", MESSAGE_EXPECTATION);
71
+ const state = {
72
+ called: false,
73
+ cleared: false,
74
+ value: void 0
75
+ };
76
+ const fn = (...parameters) => {
77
+ if (state.cleared) throw new Error(MESSAGE_CLEARED);
78
+ if (state.called) return state.value;
79
+ state.called = true;
80
+ state.value = callback(...parameters);
81
+ return state.value;
82
+ };
83
+ Object.defineProperties(fn, {
84
+ called: { get: () => state.called },
85
+ cleared: { get: () => state.cleared }
86
+ });
87
+ fn.clear = () => {
88
+ if (!state.called || state.cleared) return;
89
+ state.cleared = true;
90
+ state.value = void 0;
91
+ };
92
+ return fn;
93
+ }
94
+ once.async = asyncOnce;
95
+ var MESSAGE_CLEARED = "Once has been cleared";
96
+ var MESSAGE_EXPECTATION = "Once expected a function";
97
+ export { once };
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import { intersection } from "./array/intersection.js";
17
17
  import { partition } from "./array/partition.js";
18
18
  import { push } from "./array/push.js";
19
19
  import { select } from "./array/select.js";
20
+ import { drop, slice, take } from "./array/slice.js";
20
21
  import { max } from "./internal/math/aggregate.js";
21
22
  import { getString, ignoreKey, join, tryDecode, tryEncode, words } from "./internal/string.js";
22
23
  import { compare } from "./internal/value/compare.js";
@@ -41,6 +42,7 @@ import { hslToHex, hslToRgb, hslToRgba } from "./color/space/hsl.js";
41
42
  import { getColor } from "./color/index.js";
42
43
  import { SizedMap } from "./sized/map.js";
43
44
  import { memoize } from "./function/memoize.js";
45
+ import { once } from "./function/once.js";
44
46
  import { debounce, throttle } from "./function/index.js";
45
47
  import { RetryError, retry } from "./function/retry.js";
46
48
  import { isError, isOk, isResult } from "./internal/result.js";
@@ -75,4 +77,4 @@ import { QueueError, queue } from "./queue.js";
75
77
  import { getRandomBoolean, getRandomCharacters, getRandomColor, getRandomHex, getRandomItem, getRandomItems } from "./random.js";
76
78
  import { attempt } from "./result/index.js";
77
79
  import { SizedSet } from "./sized/set.js";
78
- export { CancelablePromise, PromiseTimeoutError, QueueError, RetryError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, difference, endsWith, equal, error, exists, filter, find, flatten, floor, flow, toResult as fromPromise, fromQuery, toPromise as fromResult, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hasValue, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, includes, indexOf, insert, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, median, memoize, merge, min, noop, ok, omit, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, retry, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, shuffle, smush, snakeCase, sort, splice, startsWith, sum, template, throttle, timed, times, titleCase, toMap, toPromise, toQuery, toRecord, toResult, toSet, toggle, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
80
+ export { CancelablePromise, PromiseTimeoutError, QueueError, RetryError, SizedMap, SizedSet, attempt, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, count, debounce, delay, diff, difference, drop, endsWith, equal, error, exists, filter, find, flatten, floor, flow, toResult as fromPromise, fromQuery, toPromise as fromResult, getArray, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getString, getUuid, getValue, groupBy, hasValue, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, includes, indexOf, insert, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isTypedArray, join, kebabCase, logger, lowerCase, max, median, memoize, merge, min, noop, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, retry, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, shuffle, slice, smush, snakeCase, sort, splice, startsWith, sum, take, template, throttle, timed, times, titleCase, toMap, toPromise, toQuery, toRecord, toResult, toSet, toggle, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "jsdom": "^28.1",
11
11
  "oxfmt": "^0.36",
12
12
  "oxlint": "^1.51",
13
- "rolldown": "1.0.0-rc.6",
13
+ "rolldown": "1.0.0-rc.7",
14
14
  "tslib": "^2.8",
15
15
  "typescript": "^5.9",
16
16
  "vite": "8.0.0-beta.16",
@@ -184,5 +184,5 @@
184
184
  },
185
185
  "type": "module",
186
186
  "types": "./types/index.d.ts",
187
- "version": "0.156.0"
188
- }
187
+ "version": "0.158.0"
188
+ }
@@ -15,6 +15,7 @@ export * from './intersection';
15
15
  export * from './partition';
16
16
  export * from './push';
17
17
  export * from './select';
18
+ export * from './slice';
18
19
  export * from './sort';
19
20
  export * from './splice';
20
21
  export * from './to-set';
@@ -0,0 +1,245 @@
1
+ import {getArrayCallbacks} from '../internal/array/callbacks';
2
+ import type {PlainObject} from '../models';
3
+
4
+ // #region Types
5
+
6
+ type ExtractType = 'drop' | 'take';
7
+
8
+ // #endregion
9
+
10
+ // #region Functions
11
+
12
+ /**
13
+ * Drop items from the start of an array until they match a value
14
+ * @param array Original array
15
+ * @param key Key to get an item's value for matching
16
+ * @param value Value to match against
17
+ * @returns New array with items dropped
18
+ */
19
+ export function drop<Item extends PlainObject, Key extends keyof Item>(
20
+ array: Item[],
21
+ key: Key,
22
+ value: Item[Key],
23
+ ): Item[];
24
+
25
+ /**
26
+ * Drop items from the start of an array until they match a value
27
+ * @param array Original array
28
+ * @param callback Callback to get an item's value for matching
29
+ * @param value Value to match against
30
+ * @return New array with items dropped
31
+ */
32
+ export function drop<Item, Callback extends (item: Item, index: number, array: Item[]) => unknown>(
33
+ array: Item[],
34
+ callback: Callback,
35
+ value: ReturnType<Callback>,
36
+ ): Item[];
37
+
38
+ /**
39
+ * Drop items from the start of an array while they match a filter
40
+ * @param array Original array
41
+ * @param callback Filter callback to match items
42
+ * @return New array with items dropped
43
+ */
44
+ export function drop<Item extends PlainObject>(
45
+ array: Item[],
46
+ callback: (item: Item, index: number, array: Item[]) => boolean,
47
+ ): Item[];
48
+
49
+ /**
50
+ * Drop a specified number of items, from the start if `>= 0`, or from the end if `< 0`
51
+ * @param array Original array
52
+ * @param count Number of items to drop
53
+ * @returns New array with items dropped
54
+ */
55
+ export function drop(array: unknown[], count: number): unknown[];
56
+
57
+ export function drop(array: unknown[], first?: unknown, second?: unknown): unknown[] {
58
+ return extract(EXTRACT_DROP, array, first, second);
59
+ }
60
+
61
+ function extract(
62
+ type: ExtractType,
63
+ array: unknown[],
64
+ first?: unknown,
65
+ second?: unknown,
66
+ ): unknown[] {
67
+ if (!Array.isArray(array)) {
68
+ return [];
69
+ }
70
+
71
+ const {length} = array;
72
+
73
+ if (length === 0) {
74
+ return [];
75
+ }
76
+
77
+ const isTake = type === EXTRACT_TAKE;
78
+
79
+ if (typeof first === 'number') {
80
+ if (Math.abs(first) >= length) {
81
+ return isTake ? array.slice() : [];
82
+ }
83
+
84
+ if (first === 0) {
85
+ return isTake ? [] : array.slice();
86
+ }
87
+
88
+ if (isTake) {
89
+ return first >= 0 ? array.slice(0, first) : array.slice(array.length + first);
90
+ }
91
+
92
+ return first >= 0 ? array.slice(first) : array.slice(0, array.length + first);
93
+ }
94
+
95
+ const callbacks =
96
+ second == null ? getArrayCallbacks(first) : getArrayCallbacks(undefined, undefined, first);
97
+
98
+ const isBoolean = callbacks?.bool != null;
99
+
100
+ if (callbacks?.bool == null && callbacks?.value == null) {
101
+ return isTake ? array.slice() : [];
102
+ }
103
+
104
+ const extracted: unknown[] = [];
105
+
106
+ let push = false;
107
+
108
+ for (let index = 0; index < length; index += 1) {
109
+ const item = array[index];
110
+
111
+ const matches = isBoolean
112
+ ? callbacks.bool!(item, index, array)
113
+ : Object.is(callbacks!.value!(item, index, array), second);
114
+
115
+ if (isTake) {
116
+ if (isBoolean ? !matches : matches) {
117
+ break;
118
+ }
119
+
120
+ extracted.push(item);
121
+
122
+ continue;
123
+ }
124
+
125
+ if (push) {
126
+ extracted.push(item);
127
+ } else if (isBoolean ? !matches : matches) {
128
+ push = true;
129
+
130
+ if (isBoolean) {
131
+ extracted.push(item);
132
+ }
133
+ }
134
+ }
135
+
136
+ return extracted;
137
+ }
138
+
139
+ /**
140
+ * Slice an array, returning a new array with a specified range of items
141
+ * @param array Original array
142
+ * @param start Start index _(inclusive)_
143
+ * @param end End index _(exclusive)_
144
+ * @return New array with sliced items
145
+ */
146
+ export function slice<Item>(array: Item[], start: number, end: number): Item[];
147
+
148
+ /**
149
+ * Slice an array, returning a new array with a specified number of items
150
+ * @param array Original array
151
+ * @param count Maximum sixe of the new array
152
+ * @return New array with sliced items
153
+ */
154
+ export function slice<Item>(array: Item[], count: number): Item[];
155
+
156
+ /**
157
+ * Slice an array
158
+ * @param array Array to slice
159
+ * @returns Sliced array
160
+ */
161
+ export function slice<Item>(array: Item[]): Item[];
162
+
163
+ export function slice(array: unknown[], first?: number, second?: number): unknown[] {
164
+ if (!Array.isArray(array) || array.length === 0) {
165
+ return [];
166
+ }
167
+
168
+ const firstIsNumber = typeof first === 'number';
169
+ const secondIsNumber = typeof second === 'number';
170
+
171
+ if (!firstIsNumber && !secondIsNumber) {
172
+ return array.slice();
173
+ }
174
+
175
+ if (!secondIsNumber) {
176
+ return first! >= 0 ? array.slice(0, first) : array.slice(array.length + first!);
177
+ }
178
+
179
+ if (!firstIsNumber) {
180
+ return array.slice();
181
+ }
182
+
183
+ return first! >= 0
184
+ ? array.slice(first!, second!)
185
+ : array.slice(array.length + first!, array.length + second!);
186
+ }
187
+
188
+ /**
189
+ * Take items from the start of an array until they match a value
190
+ * @param array Original array
191
+ * @param key Key to get an item's value for matching
192
+ * @param value Value to match against
193
+ * @returns New array with taken items
194
+ */
195
+ export function take<Item extends PlainObject, Key extends keyof Item>(
196
+ array: Item[],
197
+ key: Key,
198
+ value: Item[Key],
199
+ ): Item[];
200
+
201
+ /**
202
+ * Take items from the start of an array until they match a value
203
+ * @param array Original array
204
+ * @param callback Callback to get an item's value for matching
205
+ * @param value Value to match against
206
+ * @return New array with taken items
207
+ */
208
+ export function take<Item, Callback extends (item: Item, index: number, array: Item[]) => unknown>(
209
+ array: Item[],
210
+ callback: Callback,
211
+ value: ReturnType<Callback>,
212
+ ): Item[];
213
+
214
+ /**
215
+ * Take items from the start of an array while they match a filter
216
+ * @param array Original array
217
+ * @param callback Filter callback to match items
218
+ * @return New array with taken items
219
+ */
220
+ export function take<Item extends PlainObject>(
221
+ array: Item[],
222
+ callback: (item: Item, index: number, array: Item[]) => boolean,
223
+ ): Item[];
224
+
225
+ /**
226
+ * Take a specified number of items, from the start if `>= 0`, or from the end if `< 0`
227
+ * @param array Original array
228
+ * @param count Number of items to take
229
+ * @returns New array with taken items
230
+ */
231
+ export function take(array: unknown[], count: number): unknown[];
232
+
233
+ export function take(array: unknown[], first?: unknown, second?: unknown): unknown[] {
234
+ return extract(EXTRACT_TAKE, array, first, second);
235
+ }
236
+
237
+ // #endregion
238
+
239
+ // #region Variables
240
+
241
+ const EXTRACT_DROP: ExtractType = 'drop';
242
+
243
+ const EXTRACT_TAKE: ExtractType = 'take';
244
+
245
+ // #endregion
@@ -37,5 +37,6 @@ export function throttle<Callback extends GenericCallback>(
37
37
 
38
38
  export {noop} from '../internal/function/misc';
39
39
  export {memoize, type Memoized, type MemoizedOptions} from './memoize';
40
+ export {once} from './once';
40
41
 
41
42
  // #endregion
@@ -0,0 +1,188 @@
1
+ import type {
2
+ GenericAsyncCallback,
3
+ GenericCallback,
4
+ OnceAsyncCallback,
5
+ OnceCallback,
6
+ } from '../models';
7
+ import {assert} from './assert';
8
+
9
+ // #region Types
10
+
11
+ type OnceAsyncItem<Value> = {
12
+ reject: (reason?: unknown) => void;
13
+ resolve: (value: Value) => void;
14
+ };
15
+
16
+ type OnceAsyncState<Value> = {
17
+ error: boolean;
18
+ finished: boolean;
19
+ items: OnceAsyncItem<Value>[];
20
+ } & OnceState<Value>;
21
+
22
+ type OnceState<Value> = {
23
+ called: boolean;
24
+ cleared: boolean;
25
+ value: Value;
26
+ };
27
+
28
+ // #endregion
29
+
30
+ // #region Functions
31
+
32
+ /**
33
+ * Create an asynchronous function that can only be called once, rejecting or resolving the same result on subsequent calls
34
+ * @param callback Callback to use once
35
+ * @returns Once callback
36
+ */
37
+ function asyncOnce<Callback extends GenericAsyncCallback>(
38
+ callback: Callback,
39
+ ): OnceAsyncCallback<Callback> {
40
+ assert(() => typeof callback === 'function', MESSAGE_EXPECTATION);
41
+
42
+ const state: OnceAsyncState<Awaited<ReturnType<Callback>>> = {
43
+ called: false,
44
+ cleared: false,
45
+ error: false,
46
+ finished: false,
47
+ items: [],
48
+ value: undefined as never,
49
+ };
50
+
51
+ const fn = (...parameters: Parameters<Callback>): Promise<Awaited<ReturnType<Callback>>> => {
52
+ if (state.cleared) {
53
+ return Promise.reject(new Error(MESSAGE_CLEARED));
54
+ }
55
+
56
+ if (state.finished) {
57
+ return state.error ? Promise.reject(state.value) : Promise.resolve(state.value);
58
+ }
59
+
60
+ if (state.called) {
61
+ return new Promise<Awaited<ReturnType<Callback>>>((resolve, reject) => {
62
+ state.items.push({reject, resolve});
63
+ });
64
+ }
65
+
66
+ state.called = true;
67
+
68
+ return new Promise<Awaited<ReturnType<Callback>>>((resolve, reject) => {
69
+ state.items.push({reject, resolve});
70
+
71
+ void callback(...parameters)
72
+ .then(value => {
73
+ handleResult(state, value, false);
74
+ })
75
+ .catch(error => {
76
+ handleResult(state, error, true);
77
+ });
78
+ });
79
+ };
80
+
81
+ Object.defineProperties(fn, {
82
+ called: {
83
+ get: (): boolean => state.called,
84
+ },
85
+ cleared: {
86
+ get: (): boolean => state.cleared,
87
+ },
88
+ error: {
89
+ get: (): boolean => state.error,
90
+ },
91
+ finished: {
92
+ get: (): boolean => state.finished,
93
+ },
94
+ });
95
+
96
+ fn.clear = (): void => {
97
+ if (!state.called || !state.finished || state.cleared) {
98
+ return;
99
+ }
100
+
101
+ state.cleared = true;
102
+ state.value = undefined as never;
103
+ };
104
+
105
+ return fn as OnceAsyncCallback<Callback>;
106
+ }
107
+
108
+ function handleResult<Value>(state: OnceAsyncState<Value>, value: unknown, error: boolean): void {
109
+ state.error = error;
110
+ state.finished = true;
111
+ state.value = value as Value;
112
+
113
+ const items = state.items.splice(0);
114
+ const {length} = items;
115
+
116
+ for (let index = 0; index < length; index += 1) {
117
+ const {reject, resolve} = items[index];
118
+
119
+ if (error) {
120
+ reject(value);
121
+ } else {
122
+ resolve(value as Value);
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Create a function that can only be called once, returning the same value on subsequent calls
129
+ * @param callback Callback to use once
130
+ * @returns Once callback
131
+ */
132
+ export function once<Callback extends GenericCallback>(callback: Callback): OnceCallback<Callback> {
133
+ assert(() => typeof callback === 'function', MESSAGE_EXPECTATION);
134
+
135
+ const state: OnceState<ReturnType<Callback>> = {
136
+ called: false,
137
+ cleared: false,
138
+ value: undefined as never,
139
+ };
140
+
141
+ const fn = (...parameters: Parameters<Callback>): ReturnType<Callback> => {
142
+ if (state.cleared) {
143
+ throw new Error(MESSAGE_CLEARED);
144
+ }
145
+
146
+ if (state.called) {
147
+ return state.value;
148
+ }
149
+
150
+ state.called = true;
151
+
152
+ state.value = callback(...parameters);
153
+
154
+ return state.value;
155
+ };
156
+
157
+ Object.defineProperties(fn, {
158
+ called: {
159
+ get: (): boolean => state.called,
160
+ },
161
+ cleared: {
162
+ get: (): boolean => state.cleared,
163
+ },
164
+ });
165
+
166
+ fn.clear = (): void => {
167
+ if (!state.called || state.cleared) {
168
+ return;
169
+ }
170
+
171
+ state.cleared = true;
172
+ state.value = undefined as never;
173
+ };
174
+
175
+ return fn as OnceCallback<Callback>;
176
+ }
177
+
178
+ once.async = asyncOnce;
179
+
180
+ // #endregion
181
+
182
+ // #region Variables
183
+
184
+ const MESSAGE_CLEARED = 'Once has been cleared';
185
+
186
+ const MESSAGE_EXPECTATION = 'Once expected a function';
187
+
188
+ // #endregion
package/src/models.ts CHANGED
@@ -140,6 +140,41 @@ export type NumericalValues<Item extends PlainObject> = {
140
140
  [Key in keyof Item as Item[Key] extends number ? Key : never]: Item[Key];
141
141
  };
142
142
 
143
+ /**
144
+ * An asynchronous function that can only be called once, returning the same value on subsequent calls
145
+ */
146
+ export type OnceAsyncCallback<Callback extends GenericAsyncCallback> = {
147
+ /**
148
+ * Did the callback's promise reject?
149
+ */
150
+ readonly error: boolean;
151
+ /**
152
+ * Has the callback finished?
153
+ */
154
+ readonly finished: boolean;
155
+ } & Callback &
156
+ OnceCallbackProperties;
157
+
158
+ /**
159
+ * A callback function that can only be called once, returning the same value on subsequent calls
160
+ */
161
+ export type OnceCallback<Callback extends GenericCallback> = Callback & OnceCallbackProperties;
162
+
163
+ type OnceCallbackProperties = {
164
+ /**
165
+ * Has the callback been called?
166
+ */
167
+ readonly called: boolean;
168
+ /**
169
+ * Has the callback's value been cleared?
170
+ */
171
+ readonly cleared: boolean;
172
+ /**
173
+ * Clear the callback's cached value
174
+ */
175
+ clear: () => void;
176
+ };
177
+
143
178
  /**
144
179
  * A generic object
145
180
  */
@@ -14,6 +14,7 @@ export * from './intersection';
14
14
  export * from './partition';
15
15
  export * from './push';
16
16
  export * from './select';
17
+ export * from './slice';
17
18
  export * from './sort';
18
19
  export * from './splice';
19
20
  export * from './to-set';