@gesslar/toolkit 4.3.0 → 4.4.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
@@ -5,7 +5,7 @@
5
5
  "name": "gesslar",
6
6
  "url": "https://gesslar.dev"
7
7
  },
8
- "version": "4.3.0",
8
+ "version": "4.4.0",
9
9
  "license": "Unlicense",
10
10
  "homepage": "https://github.com/gesslar/toolkit#readme",
11
11
  "repository": {
@@ -85,9 +85,9 @@
85
85
  "devDependencies": {
86
86
  "@gesslar/uglier": "^2.2.0",
87
87
  "@rollup/plugin-node-resolve": "^16.0.3",
88
- "rollup": "^4.59.0",
89
88
  "eslint": "^10.0.3",
90
89
  "happy-dom": "^20.8.4",
90
+ "rollup": "^4.59.0",
91
91
  "typescript": "^5.9.3"
92
92
  }
93
93
  }
@@ -1,3 +1,4 @@
1
+ import Data from "./Data.js"
1
2
  import Sass from "./Sass.js"
2
3
  import Valid from "./Valid.js"
3
4
  /**
@@ -10,29 +11,45 @@ export default class Time {
10
11
  * The returned promise includes a timerId property that can be used with cancel().
11
12
  *
12
13
  * @param {number} delay - Delay in milliseconds before resolving (must be >= 0)
13
- * @param {unknown} [value] - Optional value to resolve with after the delay
14
- * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value after delay, extended with timerId property
14
+ * @param {unknown} [value] - Optional value to resolve with, or a function to invoke after the delay
15
+ * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value (or function result) after delay, extended with timerId property
15
16
  * @throws {Sass} If delay is not a number or is negative
16
17
  * @example
17
18
  * // Wait 1 second then continue
18
19
  * await Time.after(1000)
19
20
  *
20
- * // Wait 1 second then get a value
21
- * const result = await Time.after(1000, 'done')
21
+ * // Debounce: only apply the latest input after the user stops typing
22
+ * let pending = null
23
+ * function onInput(text) {
24
+ * Time.cancel(pending) // cancel() is a no-op if not a valid Time promise.
25
+ * pending = Time.after(300, () => applySearch(text))
26
+ * }
22
27
  *
23
- * // Create a cancellable delay
24
- * const promise = Time.after(5000, 'data')
25
- * Time.cancel(promise) // Cancel before it resolves
28
+ * // Timeout a fetch request
29
+ * const result = await Promise.race([
30
+ * fetch("/api/data"),
31
+ * Time.after(5000, () => { throw new Error("Request timed out") })
32
+ * ])
33
+ *
34
+ * // Cancellable delay
35
+ * const promise = Time.after(5000, "data")
36
+ * Time.cancel(promise) // Prevents resolution
26
37
  */
27
38
  static after(delay, value) {
28
39
  Valid.type(delay, "Number", "delay")
29
40
  Valid.assert(delay >= 0, "delay must be non-negative", delay)
30
41
 
31
42
  let timerId
32
- const promise = new Promise(resolve => {
43
+ const promise = new Promise((resolve, reject) => {
33
44
  // Cap at max 32-bit signed integer to avoid Node.js timeout overflow warning
34
45
  const safeDelay = Math.min(delay, 2147483647)
35
- timerId = setTimeout(() => resolve(value), safeDelay)
46
+ timerId = setTimeout(() => {
47
+ try {
48
+ resolve(Data.isType(value, "Function") ? value() : value)
49
+ } catch(e) {
50
+ reject(e)
51
+ }
52
+ }, safeDelay)
36
53
  })
37
54
  promise.timerId = timerId
38
55
 
@@ -8,19 +8,29 @@ export default class Time {
8
8
  * The returned promise includes a timerId property that can be used with cancel().
9
9
  *
10
10
  * @param {number} delay - Delay in milliseconds before resolving (must be >= 0)
11
- * @param {unknown} [value] - Optional value to resolve with after the delay
12
- * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value after delay, extended with timerId property
11
+ * @param {unknown} [value] - Optional value to resolve with, or a function to invoke after the delay
12
+ * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value (or function result) after delay, extended with timerId property
13
13
  * @throws {Sass} If delay is not a number or is negative
14
14
  * @example
15
15
  * // Wait 1 second then continue
16
16
  * await Time.after(1000)
17
17
  *
18
- * // Wait 1 second then get a value
19
- * const result = await Time.after(1000, 'done')
18
+ * // Debounce: only apply the latest input after the user stops typing
19
+ * let pending = null
20
+ * function onInput(text) {
21
+ * Time.cancel(pending) // cancel() is a no-op if not a valid Time promise.
22
+ * pending = Time.after(300, () => applySearch(text))
23
+ * }
20
24
  *
21
- * // Create a cancellable delay
22
- * const promise = Time.after(5000, 'data')
23
- * Time.cancel(promise) // Cancel before it resolves
25
+ * // Timeout a fetch request
26
+ * const result = await Promise.race([
27
+ * fetch("/api/data"),
28
+ * Time.after(5000, () => { throw new Error("Request timed out") })
29
+ * ])
30
+ *
31
+ * // Cancellable delay
32
+ * const promise = Time.after(5000, "data")
33
+ * Time.cancel(promise) // Prevents resolution
24
34
  */
25
35
  static after(delay: number, value?: unknown): Promise<unknown> & {
26
36
  timerId: number;
@@ -1 +1 @@
1
- {"version":3,"file":"Time.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Time.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH;IACE;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAfW,MAAM,UACN,OAAO,GACL,OAAO,CAAC,OAAO,CAAC,GAAG;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CA0BhD;IAED;;;;;;;;;OASG;IACH,uBANW,OAAO,CAAC,OAAO,CAAC,GAAG;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,GACnC,IAAI,CAQhB;CACF"}
1
+ {"version":3,"file":"Time.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Time.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,oBAzBW,MAAM,UACN,OAAO,GACL,OAAO,CAAC,OAAO,CAAC,GAAG;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CA0ChD;IAED;;;;;;;;;OASG;IACH,uBANW,OAAO,CAAC,OAAO,CAAC,GAAG;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,GACnC,IAAI,CAQhB;CACF"}
@@ -1,4 +1,4 @@
1
- // @gesslar/toolkit v4.3.0 - ES module bundle
1
+ // @gesslar/toolkit v4.4.0 - ES module bundle
2
2
  /**
3
3
  * @file Tantrum.js
4
4
  *
@@ -4170,29 +4170,45 @@ class Time {
4170
4170
  * The returned promise includes a timerId property that can be used with cancel().
4171
4171
  *
4172
4172
  * @param {number} delay - Delay in milliseconds before resolving (must be >= 0)
4173
- * @param {unknown} [value] - Optional value to resolve with after the delay
4174
- * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value after delay, extended with timerId property
4173
+ * @param {unknown} [value] - Optional value to resolve with, or a function to invoke after the delay
4174
+ * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value (or function result) after delay, extended with timerId property
4175
4175
  * @throws {Sass} If delay is not a number or is negative
4176
4176
  * @example
4177
4177
  * // Wait 1 second then continue
4178
4178
  * await Time.after(1000)
4179
4179
  *
4180
- * // Wait 1 second then get a value
4181
- * const result = await Time.after(1000, 'done')
4180
+ * // Debounce: only apply the latest input after the user stops typing
4181
+ * let pending = null
4182
+ * function onInput(text) {
4183
+ * Time.cancel(pending) // cancel() is a no-op if not a valid Time promise.
4184
+ * pending = Time.after(300, () => applySearch(text))
4185
+ * }
4182
4186
  *
4183
- * // Create a cancellable delay
4184
- * const promise = Time.after(5000, 'data')
4185
- * Time.cancel(promise) // Cancel before it resolves
4187
+ * // Timeout a fetch request
4188
+ * const result = await Promise.race([
4189
+ * fetch("/api/data"),
4190
+ * Time.after(5000, () => { throw new Error("Request timed out") })
4191
+ * ])
4192
+ *
4193
+ * // Cancellable delay
4194
+ * const promise = Time.after(5000, "data")
4195
+ * Time.cancel(promise) // Prevents resolution
4186
4196
  */
4187
4197
  static after(delay, value) {
4188
4198
  Valid.type(delay, "Number", "delay");
4189
4199
  Valid.assert(delay >= 0, "delay must be non-negative", delay);
4190
4200
 
4191
4201
  let timerId;
4192
- const promise = new Promise(resolve => {
4202
+ const promise = new Promise((resolve, reject) => {
4193
4203
  // Cap at max 32-bit signed integer to avoid Node.js timeout overflow warning
4194
4204
  const safeDelay = Math.min(delay, 2147483647);
4195
- timerId = setTimeout(() => resolve(value), safeDelay);
4205
+ timerId = setTimeout(() => {
4206
+ try {
4207
+ resolve(Data.isType(value, "Function") ? value() : value);
4208
+ } catch(e) {
4209
+ reject(e);
4210
+ }
4211
+ }, safeDelay);
4196
4212
  });
4197
4213
  promise.timerId = timerId;
4198
4214
 
@@ -1,4 +1,4 @@
1
- // @gesslar/toolkit v4.3.0 - UMD bundle
1
+ // @gesslar/toolkit v4.4.0 - UMD bundle
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -4176,29 +4176,45 @@
4176
4176
  * The returned promise includes a timerId property that can be used with cancel().
4177
4177
  *
4178
4178
  * @param {number} delay - Delay in milliseconds before resolving (must be >= 0)
4179
- * @param {unknown} [value] - Optional value to resolve with after the delay
4180
- * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value after delay, extended with timerId property
4179
+ * @param {unknown} [value] - Optional value to resolve with, or a function to invoke after the delay
4180
+ * @returns {Promise<unknown> & {timerId: number}} Promise that resolves with the value (or function result) after delay, extended with timerId property
4181
4181
  * @throws {Sass} If delay is not a number or is negative
4182
4182
  * @example
4183
4183
  * // Wait 1 second then continue
4184
4184
  * await Time.after(1000)
4185
4185
  *
4186
- * // Wait 1 second then get a value
4187
- * const result = await Time.after(1000, 'done')
4186
+ * // Debounce: only apply the latest input after the user stops typing
4187
+ * let pending = null
4188
+ * function onInput(text) {
4189
+ * Time.cancel(pending) // cancel() is a no-op if not a valid Time promise.
4190
+ * pending = Time.after(300, () => applySearch(text))
4191
+ * }
4188
4192
  *
4189
- * // Create a cancellable delay
4190
- * const promise = Time.after(5000, 'data')
4191
- * Time.cancel(promise) // Cancel before it resolves
4193
+ * // Timeout a fetch request
4194
+ * const result = await Promise.race([
4195
+ * fetch("/api/data"),
4196
+ * Time.after(5000, () => { throw new Error("Request timed out") })
4197
+ * ])
4198
+ *
4199
+ * // Cancellable delay
4200
+ * const promise = Time.after(5000, "data")
4201
+ * Time.cancel(promise) // Prevents resolution
4192
4202
  */
4193
4203
  static after(delay, value) {
4194
4204
  Valid.type(delay, "Number", "delay");
4195
4205
  Valid.assert(delay >= 0, "delay must be non-negative", delay);
4196
4206
 
4197
4207
  let timerId;
4198
- const promise = new Promise(resolve => {
4208
+ const promise = new Promise((resolve, reject) => {
4199
4209
  // Cap at max 32-bit signed integer to avoid Node.js timeout overflow warning
4200
4210
  const safeDelay = Math.min(delay, 2147483647);
4201
- timerId = setTimeout(() => resolve(value), safeDelay);
4211
+ timerId = setTimeout(() => {
4212
+ try {
4213
+ resolve(Data.isType(value, "Function") ? value() : value);
4214
+ } catch(e) {
4215
+ reject(e);
4216
+ }
4217
+ }, safeDelay);
4202
4218
  });
4203
4219
  promise.timerId = timerId;
4204
4220