@develia/commons 0.4.25 → 0.5.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.
Files changed (81) hide show
  1. package/dist/array.d.ts +10 -0
  2. package/dist/array.d.ts.map +1 -1
  3. package/dist/array.js +18 -0
  4. package/dist/array.js.map +1 -1
  5. package/dist/async-pool-executor.d.ts +3 -5
  6. package/dist/async-pool-executor.d.ts.map +1 -1
  7. package/dist/async-pool-executor.js +9 -9
  8. package/dist/async-pool-executor.js.map +1 -1
  9. package/dist/browser/form-utilities.d.ts +0 -2
  10. package/dist/browser/form-utilities.d.ts.map +1 -1
  11. package/dist/browser/form-utilities.js +3 -23
  12. package/dist/browser/form-utilities.js.map +1 -1
  13. package/dist/browser/geo-location.js +3 -3
  14. package/dist/browser/geo-location.js.map +1 -1
  15. package/dist/browser/native-bridge.d.ts +1 -1
  16. package/dist/browser/native-bridge.d.ts.map +1 -1
  17. package/dist/browser/native-bridge.js +2 -2
  18. package/dist/browser/native-bridge.js.map +1 -1
  19. package/dist/cancellable-promise.d.ts +8 -2
  20. package/dist/cancellable-promise.d.ts.map +1 -1
  21. package/dist/cancellable-promise.js +9 -3
  22. package/dist/cancellable-promise.js.map +1 -1
  23. package/dist/clean-url-search-params.js +3 -3
  24. package/dist/clean-url-search-params.js.map +1 -1
  25. package/dist/collections/from.d.ts +31 -11
  26. package/dist/collections/from.d.ts.map +1 -1
  27. package/dist/collections/from.js +73 -48
  28. package/dist/collections/from.js.map +1 -1
  29. package/dist/draft.d.ts +2 -2
  30. package/dist/draft.d.ts.map +1 -1
  31. package/dist/draft.js +2 -2
  32. package/dist/draft.js.map +1 -1
  33. package/dist/functions.d.ts +2 -2
  34. package/dist/functions.d.ts.map +1 -1
  35. package/dist/functions.js +1 -1
  36. package/dist/functions.js.map +1 -1
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/math.d.ts +14 -5
  42. package/dist/math.d.ts.map +1 -1
  43. package/dist/math.js +16 -5
  44. package/dist/math.js.map +1 -1
  45. package/dist/string.d.ts +5 -0
  46. package/dist/string.d.ts.map +1 -1
  47. package/dist/string.js +8 -3
  48. package/dist/string.js.map +1 -1
  49. package/dist/timespan.d.ts +5 -5
  50. package/dist/timespan.d.ts.map +1 -1
  51. package/dist/timespan.js +5 -5
  52. package/dist/timespan.js.map +1 -1
  53. package/dist/types.d.ts +0 -1
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js.map +1 -1
  56. package/dist/utilities.d.ts +11 -9
  57. package/dist/utilities.d.ts.map +1 -1
  58. package/dist/utilities.js +23 -23
  59. package/dist/utilities.js.map +1 -1
  60. package/dist/uuid.d.ts +73 -0
  61. package/dist/uuid.d.ts.map +1 -0
  62. package/dist/uuid.js +129 -0
  63. package/dist/uuid.js.map +1 -0
  64. package/package.json +5 -1
  65. package/src/array.ts +19 -0
  66. package/src/async-pool-executor.ts +9 -9
  67. package/src/browser/form-utilities.ts +3 -32
  68. package/src/browser/geo-location.ts +3 -3
  69. package/src/browser/native-bridge.ts +2 -2
  70. package/src/cancellable-promise.ts +9 -3
  71. package/src/clean-url-search-params.ts +3 -3
  72. package/src/collections/from.ts +91 -49
  73. package/src/draft.ts +3 -3
  74. package/src/functions.ts +3 -3
  75. package/src/index.ts +2 -1
  76. package/src/math.ts +17 -5
  77. package/src/string.ts +9 -3
  78. package/src/timespan.ts +5 -5
  79. package/src/types.ts +0 -1
  80. package/src/utilities.ts +27 -29
  81. package/src/uuid.ts +153 -0
package/dist/array.d.ts CHANGED
@@ -25,6 +25,16 @@ export declare function pull<T>(array: Array<T>, ...items: Array<T>): number;
25
25
  * @return {Array<Array<T>>} The array of chunks.
26
26
  */
27
27
  export declare function chunk<T>(array: Array<T>, size: number): Array<Array<T>>;
28
+ /**
29
+ * A copy of the array with the element at one index moved to another, the others shifting to make room; the array
30
+ * stays as it was. An index out of the array leaves the copy in the same order.
31
+ * @template T
32
+ * @param {ReadonlyArray<T>} array - The array.
33
+ * @param {number} fromIndex - Index of the element to move.
34
+ * @param {number} toIndex - Index the element ends at.
35
+ * @return {Array<T>} The copy, in the new order.
36
+ */
37
+ export declare function moveItem<T>(array: ReadonlyArray<T>, fromIndex: number, toIndex: number): Array<T>;
28
38
  /**
29
39
  * Removes all elements from the array, mutating it.
30
40
  * @template T
@@ -1 +1 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAC,MAAM,YAAY,CAAC;AAGvD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;QACjC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,IAAI,CAAC;QACd,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1C,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;KACrC;CACJ;AAGD;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAWnE;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAOvE;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAc3E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAMpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAQjC"}
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAC,MAAM,YAAY,CAAC;AAGvD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;QACjC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,IAAI,CAAC;QACd,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1C,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;KACrC;CACJ;AAGD;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAWnE;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAOvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAQjG;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAc3E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAMpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAQjC"}
package/dist/array.js CHANGED
@@ -34,6 +34,24 @@ export function chunk(array, size) {
34
34
  }
35
35
  return result;
36
36
  }
37
+ /**
38
+ * A copy of the array with the element at one index moved to another, the others shifting to make room; the array
39
+ * stays as it was. An index out of the array leaves the copy in the same order.
40
+ * @template T
41
+ * @param {ReadonlyArray<T>} array - The array.
42
+ * @param {number} fromIndex - Index of the element to move.
43
+ * @param {number} toIndex - Index the element ends at.
44
+ * @return {Array<T>} The copy, in the new order.
45
+ */
46
+ export function moveItem(array, fromIndex, toIndex) {
47
+ const result = [...array];
48
+ if (fromIndex < 0 || fromIndex >= result.length || toIndex < 0 || toIndex >= result.length) {
49
+ return result;
50
+ }
51
+ const [item] = result.splice(fromIndex, 1);
52
+ result.splice(toIndex, 0, item);
53
+ return result;
54
+ }
37
55
  /**
38
56
  * Removes all elements from the array, mutating it.
39
57
  * @template T
package/dist/array.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAa3C;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAI,KAAe,EAAE,GAAG,KAAe;IAEvD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACnE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACvB,MAAM,EAAE,CAAC;QACb,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAI,KAAe,EAAE,IAAY;IAClD,IAAI,IAAI,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAI,KAAe;IACpC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAI,KAAe,EAAC,SAAuB;IAC7D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB;QACxC,CAAC;aAAM,CAAC;YACJ,CAAC,EAAE,CAAC;QACR,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAI,KAAe,EAAE,OAAU;IACvD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU;IACtB,MAAM,MAAM,GAAG,KAA2C,CAAC;IAE3D,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC1B,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import type {Constructor, Predicate} from \"./types.js\";\nimport {monkeyPatch} from \"./utilities.js\";\n\ndeclare global {\n interface Array<T> {\n pull(...items: Array<T>): number;\n chunk(size: number): Array<Array<T>>;\n clear(): void;\n remove(predicate: Predicate<T>): Array<T>;\n pushIfAbsent(element: T): boolean;\n }\n}\n\n\n/**\n * Removes all given values from the provided array and returns the number of removed elements.\n * The operation mutates the original array.\n * @template T\n * @param {Array<T>} array - The array to modify by removing specified items.\n * @param {...T} items - The values to remove from the array.\n * @return {number} The number of elements removed from the array.\n */\nexport function pull<T>(array: Array<T>, ...items: Array<T>): number {\n\n let output = 0;\n for (const item of items) {\n let index;\n while ((index = array.findIndex(val => Object.is(val, item))) !== -1) {\n array.splice(index, 1);\n output++;\n }\n }\n return output;\n}\n\n/**\n * Splits an array into chunks of a given size.\n * @template T\n * @param {Array<T>} array - The array to split.\n * @param {number} size - The size of each chunk.\n * @return {Array<Array<T>>} The array of chunks.\n */\nexport function chunk<T>(array: Array<T>, size: number): Array<Array<T>> {\n if (size <= 0) throw new Error(\"Size must be greater than 0\");\n const result: Array<Array<T>> = [];\n for (let i = 0; i < array.length; i += size) {\n result.push(array.slice(i, i + size));\n }\n return result;\n}\n\n/**\n * Removes all elements from the array, mutating it.\n * @template T\n * @param {Array<T>} array - The array to clear.\n */\nexport function clear<T>(array: Array<T>): void {\n array.length = 0;\n}\n\n/**\n * Removes all elements from the array that satisfy the predicate.\n * The operation mutates the original array.\n * @template T\n * @return {Array<T>} An array of removed elements.\n */\nexport function remove<T>(array: Array<T>,predicate: Predicate<T>): Array<T> {\n const removed: Array<T> = [];\n let i = 0;\n\n while (i < array.length) {\n if (predicate(array[i])) {\n removed.push(array[i]);\n array.splice(i, 1); // muta el array\n } else {\n i++;\n }\n }\n\n return removed;\n}\n\n/**\n * Adds an element to the array if it's not already present.\n * The operation mutates the original array.\n * @template T\n * @param {Array<T>} array - The array to modify.\n * @param {T} element - The element to add if absent.\n * @return {boolean} True if the element was added, false otherwise.\n */\nexport function pushIfAbsent<T>(array: Array<T>, element: T): boolean {\n if (!array.includes(element)) {\n array.push(element);\n return true;\n }\n return false;\n}\n\n/**\n * Patches the Array prototype with the methods defined in this module:\n * - pull\n * - chunk\n * - clear\n * - remove\n * - pushIfAbsent\n *\n * Each method is added only if it doesn't already exist on Array.prototype.\n */\nexport function patchArray(): void {\n const target = Array as unknown as Constructor<Array<any>>;\n\n monkeyPatch(target, pull);\n monkeyPatch(target, chunk);\n monkeyPatch(target, clear);\n monkeyPatch(target, remove);\n monkeyPatch(target, pushIfAbsent);\n}"]}
1
+ {"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Constructor, Predicate} from \"./types.js\";\nimport {monkeyPatch} from \"./utilities.js\";\n\ndeclare global {\n interface Array<T> {\n pull(...items: Array<T>): number;\n chunk(size: number): Array<Array<T>>;\n clear(): void;\n remove(predicate: Predicate<T>): Array<T>;\n pushIfAbsent(element: T): boolean;\n }\n}\n\n\n/**\n * Removes all given values from the provided array and returns the number of removed elements.\n * The operation mutates the original array.\n * @template T\n * @param {Array<T>} array - The array to modify by removing specified items.\n * @param {...T} items - The values to remove from the array.\n * @return {number} The number of elements removed from the array.\n */\nexport function pull<T>(array: Array<T>, ...items: Array<T>): number {\n\n let output = 0;\n for (const item of items) {\n let index;\n while ((index = array.findIndex(val => Object.is(val, item))) !== -1) {\n array.splice(index, 1);\n output++;\n }\n }\n return output;\n}\n\n/**\n * Splits an array into chunks of a given size.\n * @template T\n * @param {Array<T>} array - The array to split.\n * @param {number} size - The size of each chunk.\n * @return {Array<Array<T>>} The array of chunks.\n */\nexport function chunk<T>(array: Array<T>, size: number): Array<Array<T>> {\n if (size <= 0) throw new Error(\"Size must be greater than 0\");\n const result: Array<Array<T>> = [];\n for (let i = 0; i < array.length; i += size) {\n result.push(array.slice(i, i + size));\n }\n return result;\n}\n\n/**\n * A copy of the array with the element at one index moved to another, the others shifting to make room; the array\n * stays as it was. An index out of the array leaves the copy in the same order.\n * @template T\n * @param {ReadonlyArray<T>} array - The array.\n * @param {number} fromIndex - Index of the element to move.\n * @param {number} toIndex - Index the element ends at.\n * @return {Array<T>} The copy, in the new order.\n */\nexport function moveItem<T>(array: ReadonlyArray<T>, fromIndex: number, toIndex: number): Array<T> {\n const result = [...array];\n if (fromIndex < 0 || fromIndex >= result.length || toIndex < 0 || toIndex >= result.length) {\n return result;\n }\n const [item] = result.splice(fromIndex, 1);\n result.splice(toIndex, 0, item as T);\n return result;\n}\n\n/**\n * Removes all elements from the array, mutating it.\n * @template T\n * @param {Array<T>} array - The array to clear.\n */\nexport function clear<T>(array: Array<T>): void {\n array.length = 0;\n}\n\n/**\n * Removes all elements from the array that satisfy the predicate.\n * The operation mutates the original array.\n * @template T\n * @return {Array<T>} An array of removed elements.\n */\nexport function remove<T>(array: Array<T>,predicate: Predicate<T>): Array<T> {\n const removed: Array<T> = [];\n let i = 0;\n\n while (i < array.length) {\n if (predicate(array[i])) {\n removed.push(array[i]);\n array.splice(i, 1); // muta el array\n } else {\n i++;\n }\n }\n\n return removed;\n}\n\n/**\n * Adds an element to the array if it's not already present.\n * The operation mutates the original array.\n * @template T\n * @param {Array<T>} array - The array to modify.\n * @param {T} element - The element to add if absent.\n * @return {boolean} True if the element was added, false otherwise.\n */\nexport function pushIfAbsent<T>(array: Array<T>, element: T): boolean {\n if (!array.includes(element)) {\n array.push(element);\n return true;\n }\n return false;\n}\n\n/**\n * Patches the Array prototype with the methods defined in this module:\n * - pull\n * - chunk\n * - clear\n * - remove\n * - pushIfAbsent\n *\n * Each method is added only if it doesn't already exist on Array.prototype.\n */\nexport function patchArray(): void {\n const target = Array as unknown as Constructor<Array<any>>;\n\n monkeyPatch(target, pull);\n monkeyPatch(target, chunk);\n monkeyPatch(target, clear);\n monkeyPatch(target, remove);\n monkeyPatch(target, pushIfAbsent);\n}"]}
@@ -19,11 +19,9 @@ export default class AsyncPoolExecutor {
19
19
  */
20
20
  submit<T>(task: Supplier<T | Promise<T>>): Promise<T>;
21
21
  /**
22
- * Waits until all tasks (both queued and active) are completed.
23
- * This method resolves only when there are no pending tasks.
24
- *
25
- * @return {Promise<void>} A promise that resolves when all tasks are complete.
22
+ * Waits until the queue is empty and no task is running, checking every check interval. It does not stop the
23
+ * executor: tasks submitted meanwhile are run and waited for too.
26
24
  */
27
- shutdown(): Promise<void>;
25
+ drain(): Promise<void>;
28
26
  }
29
27
  //# sourceMappingURL=async-pool-executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"async-pool-executor.d.ts","sourceRoot":"","sources":["../src/async-pool-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAoBzC,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAClC,OAAO,CAAC,gBAAgB,CAAS;IAEjC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,IAAI,cAAc,CAAC,KAAK,EAAE,MAAM,EAG/B;IAED,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAA8B;IAGhD;;;OAGG;gBACS,cAAc,EAAE,MAAM,EAAE,aAAa,GAAE,MAAW;IAM9D;;;;OAIG;IACI,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA0C5D;;;;;OAKG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKzC"}
1
+ {"version":3,"file":"async-pool-executor.d.ts","sourceRoot":"","sources":["../src/async-pool-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAoBzC,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAClC,OAAO,CAAC,gBAAgB,CAAS;IAEjC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,IAAI,cAAc,CAAC,KAAK,EAAE,MAAM,EAI/B;IAED,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAA8B;IAGhD;;;OAGG;gBACS,cAAc,EAAE,MAAM,EAAE,aAAa,GAAE,MAAW;IAO9D;;;;OAIG;IACI,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA0C5D;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAKtC"}
@@ -1,9 +1,9 @@
1
1
  import { delay } from "./utilities.js";
2
- function normalizeMaxConcurrency(value) {
2
+ /** @throws {RangeError} When it is not a positive integer. */
3
+ function assertValidMaxConcurrency(value) {
3
4
  if (!Number.isInteger(value) || value < 1) {
4
5
  throw new RangeError("maxConcurrency must be a positive integer");
5
6
  }
6
- return value;
7
7
  }
8
8
  function normalizeCheckInterval(value) {
9
9
  return Number.isFinite(value) ? Math.max(0, value) : 0;
@@ -13,7 +13,8 @@ export default class AsyncPoolExecutor {
13
13
  return this._maxConcurrency;
14
14
  }
15
15
  set maxConcurrency(value) {
16
- this._maxConcurrency = normalizeMaxConcurrency(value);
16
+ assertValidMaxConcurrency(value);
17
+ this._maxConcurrency = value;
17
18
  }
18
19
  /**
19
20
  * @param {number} maxConcurrency - The maximum number of concurrent tasks allowed.
@@ -21,7 +22,8 @@ export default class AsyncPoolExecutor {
21
22
  */
22
23
  constructor(maxConcurrency, checkInterval = 50) {
23
24
  this._taskQueue = [];
24
- this._maxConcurrency = normalizeMaxConcurrency(maxConcurrency);
25
+ assertValidMaxConcurrency(maxConcurrency);
26
+ this._maxConcurrency = maxConcurrency;
25
27
  this._checkIntervalMs = normalizeCheckInterval(checkInterval);
26
28
  this._activeTasks = 0;
27
29
  }
@@ -62,12 +64,10 @@ export default class AsyncPoolExecutor {
62
64
  return promise;
63
65
  }
64
66
  /**
65
- * Waits until all tasks (both queued and active) are completed.
66
- * This method resolves only when there are no pending tasks.
67
- *
68
- * @return {Promise<void>} A promise that resolves when all tasks are complete.
67
+ * Waits until the queue is empty and no task is running, checking every check interval. It does not stop the
68
+ * executor: tasks submitted meanwhile are run and waited for too.
69
69
  */
70
- async shutdown() {
70
+ async drain() {
71
71
  while (this._taskQueue.length > 0 || this._activeTasks > 0) {
72
72
  await delay(this._checkIntervalMs);
73
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"async-pool-executor.js","sourceRoot":"","sources":["../src/async-pool-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAC,MAAM,gBAAgB,CAAC;AAQrC,SAAS,uBAAuB,CAAC,KAAa;IAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IACzC,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAGlC,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,eAAe,CAAC;IAChC,CAAC;IAED,IAAI,cAAc,CAAC,KAAa;QAC5B,IAAI,CAAC,eAAe,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAE1D,CAAC;IAQD;;;OAGG;IACH,YAAY,cAAsB,EAAE,gBAAwB,EAAE;QAPtD,eAAU,GAA2B,EAAE,CAAC;QAQ5C,IAAI,CAAC,eAAe,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;QAC/D,IAAI,CAAC,gBAAgB,GAAG,sBAAsB,CAAC,aAAa,CAAC,CAAC;QAC9D,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAI,IAA8B;QAC3C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI;YACrB,OAAO,OAAO,CAAC;QAEnB,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YAElC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAEhC,OAAO,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC/C,MAAM,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACvC,CAAC;gBAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBAC3C,IAAI,UAAU,EAAE,CAAC;oBACb,IAAI,CAAC,YAAY,EAAE,CAAC;oBACpB,UAAU,CAAC,KAAK,IAAI,EAAE;wBAClB,IAAI,CAAC;4BACD,UAAU,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;wBAChD,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACb,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBAC7B,CAAC;gCAAS,CAAC;4BACP,IAAI,CAAC,YAAY,EAAE,CAAC;wBACxB,CAAC;oBACL,CAAC,CAAC,CAAC;gBACP,CAAC;YAGL,CAAC;YAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzB,CAAC,EAAE,CAAC,CAAC,CAAC;QAEN,OAAO,OAAO,CAAC;IAGnB,CAAC;IAGD;;;;;OAKG;IACI,KAAK,CAAC,QAAQ;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;CACJ","sourcesContent":["import type {Supplier} from \"./types.js\";\nimport {delay} from \"./utilities.js\";\n\ntype QueuedTask<T> = {\n task: Supplier<T | Promise<T>>;\n resolve: (value: T) => void;\n reject: (reason?: any) => void;\n};\n\nfunction normalizeMaxConcurrency(value: number): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new RangeError(\"maxConcurrency must be a positive integer\");\n }\n return value;\n}\n\nfunction normalizeCheckInterval(value: number): number {\n return Number.isFinite(value) ? Math.max(0, value) : 0;\n}\n\nexport default class AsyncPoolExecutor {\n private _checkIntervalMs: number;\n\n get maxConcurrency(): number {\n return this._maxConcurrency;\n }\n\n set maxConcurrency(value: number) {\n this._maxConcurrency = normalizeMaxConcurrency(value);\n\n }\n\n private _process: any;\n private _maxConcurrency: number;\n private _activeTasks: number;\n private _taskQueue: Array<QueuedTask<any>> = [];\n\n\n /**\n * @param {number} maxConcurrency - The maximum number of concurrent tasks allowed.\n * @param {number} [checkInterval=50] - The interval, in milliseconds, to check for capacity to run new tasks. Defaults to 50 ms.\n */\n constructor(maxConcurrency: number, checkInterval: number = 50) {\n this._maxConcurrency = normalizeMaxConcurrency(maxConcurrency);\n this._checkIntervalMs = normalizeCheckInterval(checkInterval);\n this._activeTasks = 0;\n }\n\n /**\n * Submits a deferred task to a queue for asynchronous execution and returns a Promise resolving to its result.\n * @template T\n * @param {Supplier<T>} task - The deferred task to be executed asynchronously.\n */\n public submit<T>(task: Supplier<T | Promise<T>>): Promise<T> {\n const promise = new Promise<T>((resolve, reject) => {\n this._taskQueue.push({task, resolve, reject});\n });\n\n if (this._process != null)\n return promise;\n\n this._process = setTimeout(async () => {\n\n while (this._taskQueue.length > 0) {\n\n while (this._activeTasks >= this._maxConcurrency) {\n await delay(this._checkIntervalMs);\n }\n\n const queuedTask = this._taskQueue.shift();\n if (queuedTask) {\n this._activeTasks++;\n setTimeout(async () => {\n try {\n queuedTask.resolve(await queuedTask.task());\n } catch (error) {\n queuedTask.reject(error);\n } finally {\n this._activeTasks--;\n }\n });\n }\n\n\n }\n\n this._process = null;\n }, 0);\n\n return promise;\n\n\n }\n\n\n /**\n * Waits until all tasks (both queued and active) are completed.\n * This method resolves only when there are no pending tasks.\n *\n * @return {Promise<void>} A promise that resolves when all tasks are complete.\n */\n public async shutdown(): Promise<void> {\n while (this._taskQueue.length > 0 || this._activeTasks > 0) {\n await delay(this._checkIntervalMs);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"async-pool-executor.js","sourceRoot":"","sources":["../src/async-pool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Supplier} from \"./types.js\";\nimport {delay} from \"./utilities.js\";\n\ntype QueuedTask<T> = {\n task: Supplier<T | Promise<T>>;\n resolve: (value: T) => void;\n reject: (reason?: any) => void;\n};\n\n/** @throws {RangeError} When it is not a positive integer. */\nfunction assertValidMaxConcurrency(value: number): void {\n if (!Number.isInteger(value) || value < 1) {\n throw new RangeError(\"maxConcurrency must be a positive integer\");\n }\n}\n\nfunction normalizeCheckInterval(value: number): number {\n return Number.isFinite(value) ? Math.max(0, value) : 0;\n}\n\nexport default class AsyncPoolExecutor {\n private _checkIntervalMs: number;\n\n get maxConcurrency(): number {\n return this._maxConcurrency;\n }\n\n set maxConcurrency(value: number) {\n assertValidMaxConcurrency(value);\n this._maxConcurrency = value;\n\n }\n\n private _process: any;\n private _maxConcurrency: number;\n private _activeTasks: number;\n private _taskQueue: Array<QueuedTask<any>> = [];\n\n\n /**\n * @param {number} maxConcurrency - The maximum number of concurrent tasks allowed.\n * @param {number} [checkInterval=50] - The interval, in milliseconds, to check for capacity to run new tasks. Defaults to 50 ms.\n */\n constructor(maxConcurrency: number, checkInterval: number = 50) {\n assertValidMaxConcurrency(maxConcurrency);\n this._maxConcurrency = maxConcurrency;\n this._checkIntervalMs = normalizeCheckInterval(checkInterval);\n this._activeTasks = 0;\n }\n\n /**\n * Submits a deferred task to a queue for asynchronous execution and returns a Promise resolving to its result.\n * @template T\n * @param {Supplier<T>} task - The deferred task to be executed asynchronously.\n */\n public submit<T>(task: Supplier<T | Promise<T>>): Promise<T> {\n const promise = new Promise<T>((resolve, reject) => {\n this._taskQueue.push({task, resolve, reject});\n });\n\n if (this._process != null)\n return promise;\n\n this._process = setTimeout(async () => {\n\n while (this._taskQueue.length > 0) {\n\n while (this._activeTasks >= this._maxConcurrency) {\n await delay(this._checkIntervalMs);\n }\n\n const queuedTask = this._taskQueue.shift();\n if (queuedTask) {\n this._activeTasks++;\n setTimeout(async () => {\n try {\n queuedTask.resolve(await queuedTask.task());\n } catch (error) {\n queuedTask.reject(error);\n } finally {\n this._activeTasks--;\n }\n });\n }\n\n\n }\n\n this._process = null;\n }, 0);\n\n return promise;\n\n\n }\n\n\n /**\n * Waits until the queue is empty and no task is running, checking every check interval. It does not stop the\n * executor: tasks submitted meanwhile are run and waited for too.\n */\n public async drain(): Promise<void> {\n while (this._taskQueue.length > 0 || this._activeTasks > 0) {\n await delay(this._checkIntervalMs);\n }\n }\n}\n"]}
@@ -1,4 +1,3 @@
1
- import type { Consumer } from "../types.js";
2
1
  /**
3
2
  * Submits a form via AJAX and returns a Promise that resolves to the Response object.
4
3
  *
@@ -16,5 +15,4 @@ export declare function formToObject(form: HTMLFormElement): Record<string, Form
16
15
  * @return {FormData} - The FormData object representing the converted data.
17
16
  */
18
17
  export declare function objectToFormData(data: Record<string, any>): FormData;
19
- export declare function ajaxSubmission(selectorOrElement: HTMLFormElement | string, onSuccess?: Consumer<any>, onFailure?: Consumer<any>): void;
20
18
  //# sourceMappingURL=form-utilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-utilities.d.ts","sourceRoot":"","sources":["../../src/browser/form-utilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAG1C;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,iBAAiB,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmB/F;AAGD,wBAAgB,UAAU,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,GAAE,MAAM,GAAG,KAAc,EAC/B,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GACjD,IAAI,CAkDN;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAAC,CAkB7G;AAoCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,QAAQ,CAGpE;AAED,wBAAgB,cAAc,CAC1B,iBAAiB,EAAE,eAAe,GAAG,MAAM,EAC3C,SAAS,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,EACzB,SAAS,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,GAC1B,IAAI,CAuBN"}
1
+ {"version":3,"file":"form-utilities.d.ts","sourceRoot":"","sources":["../../src/browser/form-utilities.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,iBAAiB,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmB/F;AAGD,wBAAgB,UAAU,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,GAAE,MAAM,GAAG,KAAc,EAC/B,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GACjD,IAAI,CAkDN;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAAC,CAkB7G;AAoCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,QAAQ,CAGpE"}
@@ -108,13 +108,13 @@ function _appendFormDataValue(formData, key, value) {
108
108
  }
109
109
  }
110
110
  else if (value !== null && typeof value === 'object') {
111
- _objectToFormData(value, formData, key);
111
+ _appendToFormData(value, formData, key);
112
112
  }
113
113
  else {
114
114
  formData.append(key, value);
115
115
  }
116
116
  }
117
- function _objectToFormData(data, formData, parentKey = '') {
117
+ function _appendToFormData(data, formData, parentKey = '') {
118
118
  for (const key in data) {
119
119
  if (Object.prototype.hasOwnProperty.call(data, key)) {
120
120
  _appendFormDataValue(formData, parentKey ? `${parentKey}[${key}]` : key, data[key]);
@@ -130,26 +130,6 @@ function _objectToFormData(data, formData, parentKey = '') {
130
130
  */
131
131
  export function objectToFormData(data) {
132
132
  let formData = new FormData();
133
- return _objectToFormData(data, formData);
134
- }
135
- export function ajaxSubmission(selectorOrElement, onSuccess, onFailure) {
136
- const forms = typeof selectorOrElement === 'string'
137
- ? Array.from(document.querySelectorAll(selectorOrElement))
138
- .filter(el => el instanceof HTMLFormElement)
139
- : [selectorOrElement];
140
- for (const form of forms) {
141
- form.addEventListener('submit', async (event) => {
142
- event.preventDefault();
143
- try {
144
- let result = await ajaxSubmit(event.currentTarget);
145
- if (onSuccess)
146
- onSuccess(result);
147
- }
148
- catch (e) {
149
- if (onFailure)
150
- onFailure(e);
151
- }
152
- });
153
- }
133
+ return _appendToFormData(data, formData);
154
134
  }
155
135
  //# sourceMappingURL=form-utilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-utilities.js","sourceRoot":"","sources":["../../src/browser/form-utilities.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Consumer} from \"../types.js\";\n\n\n/**\n * Submits a form via AJAX and returns a Promise that resolves to the Response object.\n *\n * @param {HTMLFormElement | string} selectorOrElement - The form element or selector.\n * @return {Promise<Response>} A Promise that resolves to the Response object.\n * @throws {Error} If the element is invalid.\n */\nexport async function ajaxSubmit(selectorOrElement: HTMLFormElement | string): Promise<Response> {\n\n const form = typeof selectorOrElement === 'string'\n ? document.querySelector(selectorOrElement)\n : selectorOrElement;\n\n if (!(form instanceof HTMLFormElement)) {\n throw new Error(\"Invalid element.\");\n }\n\n\n const formData = new FormData(form);\n const method = form.getAttribute('method') as string ?? form.method;\n const action = form.getAttribute('action') as string ?? form.action;\n\n return await fetch(action, {\n method: method,\n body: formData,\n });\n}\n\n\nexport function submitForm(\n url: string,\n data: Record<string, any>,\n method: 'POST' | 'GET' = 'POST',\n target?: '_blank' | '_self' | '_parent' | '_top'\n): void {\n\n const form = document.createElement('form');\n form.method = method.toUpperCase();\n form.action = url;\n form.style.display = 'none';\n\n if (target) {\n form.target = target;\n }\n\n /**\n * Recursively appends inputs to the form, supporting nested keys and arrays.\n * @param keyPrefix - Key path, e.g., 'user[name]' or 'tags[]'\n * @param value - The value to append (can be nested)\n */\n const appendInput = (key: string, value: any) => {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = String(value);\n form.appendChild(input);\n };\n\n const appendInputs = (keyPrefix: string, value: any) => {\n if (Array.isArray(value)) {\n for (const val of value) {\n appendInputs(`${keyPrefix}[]`, val);\n }\n } else if (value instanceof Date) {\n appendInput(keyPrefix, value.toISOString());\n } else if (typeof value === 'object' && value !== null) {\n for (const subKey in value) {\n if (Object.prototype.hasOwnProperty.call(value, subKey)) {\n appendInputs(`${keyPrefix}[${subKey}]`, value[subKey]);\n }\n }\n } else {\n appendInput(keyPrefix, value);\n }\n };\n\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n appendInputs(key, data[key]);\n }\n }\n\n document.body.appendChild(form);\n form.submit();\n}\n\nexport function formToObject(form: HTMLFormElement): Record<string, FormDataEntryValue | FormDataEntryValue[]> {\n const fd = new FormData(form);\n const out: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};\n\n for (const [key, value] of fd.entries()) {\n if (Object.prototype.hasOwnProperty.call(out, key)) {\n const current = out[key];\n if (Array.isArray(current)) {\n current.push(value);\n } else {\n out[key] = [current, value];\n }\n } else {\n out[key] = value;\n }\n }\n\n return out;\n}\n\n/**\n * Converts an object to `FormData` format recursively.\n *\n * @param {Record<string, any>} data - The object data to convert.\n * @param {FormData} formData - The `FormData` instance to append data to.\n * @param {string} parentKey - The parent key to append to child keys in the `FormData`.\n * @returns {FormData} - The `FormData` instance with the converted data.\n */\nfunction _appendFormDataValue(formData: FormData, key: string, value: any): void {\n if (value instanceof Date) {\n formData.append(key, value.toISOString());\n } else if (value instanceof File) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index++) {\n _appendFormDataValue(formData, `${key}[${index}]`, value[index]);\n }\n } else if (value !== null && typeof value === 'object') {\n _objectToFormData(value, formData, key);\n } else {\n formData.append(key, value);\n }\n}\n\nfunction _objectToFormData(data: Record<string, any>, formData: FormData, parentKey: string = ''): FormData {\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n _appendFormDataValue(formData, parentKey ? `${parentKey}[${key}]` : key, data[key]);\n }\n }\n\n return formData;\n}\n\n/**\n * Converts an object into FormData.\n *\n * @param {Record<string, any>} data - The object to be converted into FormData.\n * @return {FormData} - The FormData object representing the converted data.\n */\nexport function objectToFormData(data: Record<string, any>): FormData {\n let formData = new FormData();\n return _objectToFormData(data, formData);\n}\n\nexport function ajaxSubmission(\n selectorOrElement: HTMLFormElement | string,\n onSuccess?: Consumer<any>,\n onFailure?: Consumer<any>\n): void {\n\n const forms: HTMLFormElement[] = typeof selectorOrElement === 'string'\n ? Array.from(document.querySelectorAll(selectorOrElement))\n .filter(el => el instanceof HTMLFormElement) as HTMLFormElement[]\n : [selectorOrElement];\n\n for (const form of forms) {\n form.addEventListener('submit', async (event) => {\n event.preventDefault();\n\n try {\n let result = await ajaxSubmit(event.currentTarget as HTMLFormElement);\n if (onSuccess)\n onSuccess(result);\n } catch (e) {\n if (onFailure)\n onFailure(e);\n }\n\n\n });\n }\n}"]}
1
+ {"version":3,"file":"form-utilities.js","sourceRoot":"","sources":["../../src/browser/form-utilities.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,iBAA2C;IAExE,MAAM,IAAI,GAAG,OAAO,iBAAiB,KAAK,QAAQ;QAC9C,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,iBAAiB,CAAC;QAC3C,CAAC,CAAC,iBAAiB,CAAC;IAExB,IAAI,CAAC,CAAC,IAAI,YAAY,eAAe,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACxC,CAAC;IAGD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAW,IAAI,IAAI,CAAC,MAAM,CAAC;IACpE,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAW,IAAI,IAAI,CAAC,MAAM,CAAC;IAEpE,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE;QACvB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,QAAQ;KACjB,CAAC,CAAC;AACP,CAAC;AAGD,MAAM,UAAU,UAAU,CACtB,GAAW,EACX,IAAyB,EACzB,SAAyB,MAAM,EAC/B,MAAgD;IAGhD,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;IAClB,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAE5B,IAAI,MAAM,EAAE,CAAC;QACT,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACtB,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC;QACjB,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAE,KAAU,EAAE,EAAE;QACnD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;gBACtB,YAAY,CAAC,GAAG,SAAS,IAAI,EAAE,GAAG,CAAC,CAAC;YACxC,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YAC/B,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACrD,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;oBACtD,YAAY,CAAC,GAAG,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC3D,CAAC;YACL,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACL,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAClD,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAqB;IAC9C,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,GAAG,GAA8D,EAAE,CAAC;IAE1E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACrB,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAAC,QAAkB,EAAE,GAAW,EAAE,KAAU;IACrE,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9C,CAAC;SAAM,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC/B,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YAChD,oBAAoB,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,KAAK,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACrE,CAAC;IACL,CAAC;SAAM,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrD,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACJ,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAyB,EAAE,QAAkB,EAAE,YAAoB,EAAE;IAC5F,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAClD,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACtD,IAAI,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,OAAO,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import type {Consumer} from \"../types.js\";\n\n\n/**\n * Submits a form via AJAX and returns a Promise that resolves to the Response object.\n *\n * @param {HTMLFormElement | string} selectorOrElement - The form element or selector.\n * @return {Promise<Response>} A Promise that resolves to the Response object.\n * @throws {Error} If the element is invalid.\n */\nexport async function ajaxSubmit(selectorOrElement: HTMLFormElement | string): Promise<Response> {\n\n const form = typeof selectorOrElement === 'string'\n ? document.querySelector(selectorOrElement)\n : selectorOrElement;\n\n if (!(form instanceof HTMLFormElement)) {\n throw new Error(\"Invalid element.\");\n }\n\n\n const formData = new FormData(form);\n const method = form.getAttribute('method') as string ?? form.method;\n const action = form.getAttribute('action') as string ?? form.action;\n\n return await fetch(action, {\n method: method,\n body: formData,\n });\n}\n\n\nexport function submitForm(\n url: string,\n data: Record<string, any>,\n method: 'POST' | 'GET' = 'POST',\n target?: '_blank' | '_self' | '_parent' | '_top'\n): void {\n\n const form = document.createElement('form');\n form.method = method.toUpperCase();\n form.action = url;\n form.style.display = 'none';\n\n if (target) {\n form.target = target;\n }\n\n /**\n * Recursively appends inputs to the form, supporting nested keys and arrays.\n * @param keyPrefix - Key path, e.g., 'user[name]' or 'tags[]'\n * @param value - The value to append (can be nested)\n */\n const appendInput = (key: string, value: any) => {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = String(value);\n form.appendChild(input);\n };\n\n const appendInputs = (keyPrefix: string, value: any) => {\n if (Array.isArray(value)) {\n for (const val of value) {\n appendInputs(`${keyPrefix}[]`, val);\n }\n } else if (value instanceof Date) {\n appendInput(keyPrefix, value.toISOString());\n } else if (typeof value === 'object' && value !== null) {\n for (const subKey in value) {\n if (Object.prototype.hasOwnProperty.call(value, subKey)) {\n appendInputs(`${keyPrefix}[${subKey}]`, value[subKey]);\n }\n }\n } else {\n appendInput(keyPrefix, value);\n }\n };\n\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n appendInputs(key, data[key]);\n }\n }\n\n document.body.appendChild(form);\n form.submit();\n}\n\nexport function formToObject(form: HTMLFormElement): Record<string, FormDataEntryValue | FormDataEntryValue[]> {\n const fd = new FormData(form);\n const out: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};\n\n for (const [key, value] of fd.entries()) {\n if (Object.prototype.hasOwnProperty.call(out, key)) {\n const current = out[key];\n if (Array.isArray(current)) {\n current.push(value);\n } else {\n out[key] = [current, value];\n }\n } else {\n out[key] = value;\n }\n }\n\n return out;\n}\n\n/**\n * Converts an object to `FormData` format recursively.\n *\n * @param {Record<string, any>} data - The object data to convert.\n * @param {FormData} formData - The `FormData` instance to append data to.\n * @param {string} parentKey - The parent key to append to child keys in the `FormData`.\n * @returns {FormData} - The `FormData` instance with the converted data.\n */\nfunction _appendFormDataValue(formData: FormData, key: string, value: any): void {\n if (value instanceof Date) {\n formData.append(key, value.toISOString());\n } else if (value instanceof File) {\n formData.append(key, value);\n } else if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index++) {\n _appendFormDataValue(formData, `${key}[${index}]`, value[index]);\n }\n } else if (value !== null && typeof value === 'object') {\n _appendToFormData(value, formData, key);\n } else {\n formData.append(key, value);\n }\n}\n\nfunction _appendToFormData(data: Record<string, any>, formData: FormData, parentKey: string = ''): FormData {\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n _appendFormDataValue(formData, parentKey ? `${parentKey}[${key}]` : key, data[key]);\n }\n }\n\n return formData;\n}\n\n/**\n * Converts an object into FormData.\n *\n * @param {Record<string, any>} data - The object to be converted into FormData.\n * @return {FormData} - The FormData object representing the converted data.\n */\nexport function objectToFormData(data: Record<string, any>): FormData {\n let formData = new FormData();\n return _appendToFormData(data, formData);\n}\n"]}
@@ -13,7 +13,7 @@ function positionToGeoLocation(position) {
13
13
  timestamp,
14
14
  };
15
15
  }
16
- function geolocationError(error) {
16
+ function toGeolocationError(error) {
17
17
  switch (error.code) {
18
18
  case error.PERMISSION_DENIED:
19
19
  return new Error('Has denegado el permiso de ubicación.');
@@ -27,7 +27,7 @@ function geolocationError(error) {
27
27
  }
28
28
  function requestPosition(options) {
29
29
  return new Promise((resolve, reject) => {
30
- navigator.geolocation.getCurrentPosition((position) => resolve(positionToGeoLocation(position)), (error) => reject(geolocationError(error)), options);
30
+ navigator.geolocation.getCurrentPosition((position) => resolve(positionToGeoLocation(position)), (error) => reject(toGeolocationError(error)), options);
31
31
  });
32
32
  }
33
33
  async function ensurePermission() {
@@ -55,7 +55,7 @@ async function ensurePermission() {
55
55
  resolve();
56
56
  }, (error) => {
57
57
  permission.onchange = null;
58
- reject(geolocationError(error));
58
+ reject(toGeolocationError(error));
59
59
  }, { timeout: 30000 });
60
60
  });
61
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"geo-location.js","sourceRoot":"","sources":["../../src/browser/geo-location.ts"],"names":[],"mappings":"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","sourcesContent":["// ─── Tipos ───────────────────────────────────────────────\n\nexport interface GeoLocation {\n latitude: number;\n longitude: number;\n accuracy: number;\n altitude: number | null;\n altitudeAccuracy: number | null;\n heading: number | null;\n speed: number | null;\n timestamp: number;\n}\n\nexport interface GeoLocationOptions {\n enableHighAccuracy?: boolean;\n timeout?: number;\n maximumAge?: number;\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\nfunction positionToGeoLocation(position: GeolocationPosition): GeoLocation {\n const {coords, timestamp} = position;\n return {\n latitude: coords.latitude,\n longitude: coords.longitude,\n accuracy: coords.accuracy,\n altitude: coords.altitude,\n altitudeAccuracy: coords.altitudeAccuracy,\n heading: coords.heading,\n speed: coords.speed,\n timestamp,\n };\n}\n\nfunction geolocationError(error: GeolocationPositionError): Error {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n return new Error('Has denegado el permiso de ubicación.');\n case error.POSITION_UNAVAILABLE:\n return new Error('No se pudo determinar tu ubicación.');\n case error.TIMEOUT:\n return new Error('Tiempo de espera agotado al obtener la ubicación.');\n default:\n return new Error('Error desconocido al obtener la ubicación.');\n }\n}\n\nfunction requestPosition(options: PositionOptions): Promise<GeoLocation> {\n return new Promise((resolve, reject) => {\n navigator.geolocation.getCurrentPosition(\n (position) => resolve(positionToGeoLocation(position)),\n (error) => reject(geolocationError(error)),\n options,\n );\n });\n}\n\nasync function ensurePermission(): Promise<void> {\n if (!navigator.permissions) return;\n\n const permission = await navigator.permissions.query({name: 'geolocation'});\n\n if (permission.state === 'denied') {\n throw new Error(\n 'Permiso de ubicación denegado. Actívalo en la configuración del navegador.',\n );\n }\n\n if (permission.state === 'prompt') {\n await new Promise<void>((resolve, reject) => {\n // Escuchar cambio de estado del permiso\n permission.onchange = () => {\n permission.onchange = null;\n if (permission.state === 'granted') {\n resolve();\n } else {\n reject(new Error('Has denegado el permiso de ubicación.'));\n }\n };\n\n // Forzar el diálogo nativo del navegador\n navigator.geolocation.getCurrentPosition(\n () => {\n permission.onchange = null;\n resolve();\n },\n (error) => {\n permission.onchange = null;\n reject(geolocationError(error));\n },\n {timeout: 30000},\n );\n });\n }\n}\n\n// ─── Función principal ──────────────────────────────────\n\nexport default async function getGeoLocation(\n options: GeoLocationOptions = {},\n): Promise<GeoLocation> {\n if (typeof navigator === 'undefined' || !navigator.geolocation) {\n throw new Error('Tu navegador no soporta geolocalización.');\n }\n\n await ensurePermission();\n\n return requestPosition({\n enableHighAccuracy: options.enableHighAccuracy ?? true,\n timeout: options.timeout ?? 10000,\n maximumAge: options.maximumAge ?? 0,\n });\n}"]}
1
+ {"version":3,"file":"geo-location.js","sourceRoot":"","sources":["../../src/browser/geo-location.ts"],"names":[],"mappings":"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","sourcesContent":["// ─── Tipos ───────────────────────────────────────────────\n\nexport interface GeoLocation {\n latitude: number;\n longitude: number;\n accuracy: number;\n altitude: number | null;\n altitudeAccuracy: number | null;\n heading: number | null;\n speed: number | null;\n timestamp: number;\n}\n\nexport interface GeoLocationOptions {\n enableHighAccuracy?: boolean;\n timeout?: number;\n maximumAge?: number;\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\nfunction positionToGeoLocation(position: GeolocationPosition): GeoLocation {\n const {coords, timestamp} = position;\n return {\n latitude: coords.latitude,\n longitude: coords.longitude,\n accuracy: coords.accuracy,\n altitude: coords.altitude,\n altitudeAccuracy: coords.altitudeAccuracy,\n heading: coords.heading,\n speed: coords.speed,\n timestamp,\n };\n}\n\nfunction toGeolocationError(error: GeolocationPositionError): Error {\n switch (error.code) {\n case error.PERMISSION_DENIED:\n return new Error('Has denegado el permiso de ubicación.');\n case error.POSITION_UNAVAILABLE:\n return new Error('No se pudo determinar tu ubicación.');\n case error.TIMEOUT:\n return new Error('Tiempo de espera agotado al obtener la ubicación.');\n default:\n return new Error('Error desconocido al obtener la ubicación.');\n }\n}\n\nfunction requestPosition(options: PositionOptions): Promise<GeoLocation> {\n return new Promise((resolve, reject) => {\n navigator.geolocation.getCurrentPosition(\n (position) => resolve(positionToGeoLocation(position)),\n (error) => reject(toGeolocationError(error)),\n options,\n );\n });\n}\n\nasync function ensurePermission(): Promise<void> {\n if (!navigator.permissions) return;\n\n const permission = await navigator.permissions.query({name: 'geolocation'});\n\n if (permission.state === 'denied') {\n throw new Error(\n 'Permiso de ubicación denegado. Actívalo en la configuración del navegador.',\n );\n }\n\n if (permission.state === 'prompt') {\n await new Promise<void>((resolve, reject) => {\n // Escuchar cambio de estado del permiso\n permission.onchange = () => {\n permission.onchange = null;\n if (permission.state === 'granted') {\n resolve();\n } else {\n reject(new Error('Has denegado el permiso de ubicación.'));\n }\n };\n\n // Forzar el diálogo nativo del navegador\n navigator.geolocation.getCurrentPosition(\n () => {\n permission.onchange = null;\n resolve();\n },\n (error) => {\n permission.onchange = null;\n reject(toGeolocationError(error));\n },\n {timeout: 30000},\n );\n });\n }\n}\n\n// ─── Función principal ──────────────────────────────────\n\nexport default async function getGeoLocation(\n options: GeoLocationOptions = {},\n): Promise<GeoLocation> {\n if (typeof navigator === 'undefined' || !navigator.geolocation) {\n throw new Error('Tu navegador no soporta geolocalización.');\n }\n\n await ensurePermission();\n\n return requestPosition({\n enableHighAccuracy: options.enableHighAccuracy ?? true,\n timeout: options.timeout ?? 10000,\n maximumAge: options.maximumAge ?? 0,\n });\n}"]}
@@ -12,7 +12,7 @@ export default class NativeBridge {
12
12
  private readonly _defaultTimeout;
13
13
  private readonly _channel;
14
14
  constructor({ channel, timeout, callbackName }: BridgeOptions);
15
- private _callback;
15
+ private _settlePendingCall;
16
16
  call(method: string, data?: unknown, timeout?: number | null): Promise<unknown>;
17
17
  send(method: string, data?: unknown): void;
18
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"native-bridge.d.ts","sourceRoot":"","sources":["../../src/browser/native-bridge.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,UAAU,OAAO;IACb,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAMD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;gBAGvB,EAAE,OAAO,EAAE,OAAc,EAAE,YAAwC,EAAE,EAAE,aAAa;IAwBhG,OAAO,CAAC,SAAS;IAoBjB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBrF,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAc,GAAG,IAAI;IAIhD;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,SAAS,IAAI,IAAI;CASpB"}
1
+ {"version":3,"file":"native-bridge.d.ts","sourceRoot":"","sources":["../../src/browser/native-bridge.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,UAAU,OAAO;IACb,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAMD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;gBAGvB,EAAE,OAAO,EAAE,OAAc,EAAE,YAAwC,EAAE,EAAE,aAAa;IAwBhG,OAAO,CAAC,kBAAkB;IAoB1B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBrF,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAc,GAAG,IAAI;IAIhD;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,SAAS,IAAI,IAAI;CASpB"}
@@ -9,7 +9,7 @@ export default class NativeBridge {
9
9
  throw new Error('Channel not found');
10
10
  }
11
11
  window[callbackName] = (id, error, result) => {
12
- this._callback(id, error, result);
12
+ this._settlePendingCall(id, error, result);
13
13
  };
14
14
  // Proxy: cualquier propiedad no existente se convierte en call()
15
15
  return new Proxy(this, {
@@ -21,7 +21,7 @@ export default class NativeBridge {
21
21
  },
22
22
  });
23
23
  }
24
- _callback(id, error, result) {
24
+ _settlePendingCall(id, error, result) {
25
25
  const pending = this._pending.get(id);
26
26
  if (!pending) {
27
27
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"native-bridge.js","sourceRoot":"","sources":["../../src/browser/native-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["// ─── Tipos ───────────────────────────────────────────────\ninterface BridgeOptions {\n channel: Channel;\n timeout?: number | null;\n callbackName?: string; // ← nuevo\n}\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout> | null;\n}\n\ninterface Channel {\n postMessage: (message: string) => void;\n}\n\n\n\n// ─── Clase ──────────────────────────────────────────────\n\nexport default class NativeBridge {\n private _pending = new Map<number, PendingCall>();\n private _callId = 0;\n private readonly _defaultTimeout: number | null;\n private readonly _channel: Channel;\n\n\n constructor({ channel, timeout = 3000, callbackName = '__nativeResponseHandler' }: BridgeOptions) {\n this._defaultTimeout = timeout;\n this._channel = channel;\n\n if (!this._channel) {\n throw new Error('Channel not found');\n }\n\n (window as any)[callbackName] = (id: number, error: any, result: any) => {\n this._callback(id, error, result);\n };\n\n // Proxy: cualquier propiedad no existente se convierte en call()\n return new Proxy(this, {\n get(target: NativeBridge, prop: string | symbol) {\n if (prop in target) {\n return (target as any)[prop];\n }\n return (data?: unknown, timeout?: number | null) => target.call(String(prop), data, timeout);\n },\n }) as unknown as NativeBridge;\n }\n\n\n private _callback(id: number, error: any, result: any) {\n\n const pending = this._pending.get(id);\n if (!pending) {\n return;\n }\n\n if (pending.timer !== null) {\n clearTimeout(pending.timer);\n }\n\n this._pending.delete(id);\n\n if (error) {\n pending.reject(error instanceof Error? error : new Error(String(error)));\n } else {\n pending.resolve(result);\n }\n }\n\n call(method: string, data: unknown = null, timeout?: number | null): Promise<unknown> {\n\n\n const effectiveTimeout = timeout !== undefined ? timeout : this._defaultTimeout;\n\n return new Promise<unknown>((resolve, reject) => {\n const id = this._callId++;\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n // Solo crear timer si hay timeout\n if (effectiveTimeout !== null && effectiveTimeout > 0) {\n timer = setTimeout(() => {\n this._pending.delete(id);\n reject(new Error(`Timeout (${effectiveTimeout}ms): ${method}`));\n }, effectiveTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n this._channel!.postMessage(JSON.stringify({ id, method, data }));\n });\n }\n\n\n send(method: string, data: unknown = null): void {\n this._channel!.postMessage(JSON.stringify({ method, data }));\n }\n\n /**\n * Número de llamadas pendientes\n */\n get pendingCount(): number {\n return this._pending.size;\n }\n\n /**\n * Cancela todas las llamadas pendientes\n */\n cancelAll(): void {\n for (const [, { reject, timer }] of this._pending) {\n if (timer !== null) {\n clearTimeout(timer);\n }\n reject(new Error('Cancelled'));\n }\n this._pending.clear();\n }\n}"]}
1
+ {"version":3,"file":"native-bridge.js","sourceRoot":"","sources":["../../src/browser/native-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["// ─── Tipos ───────────────────────────────────────────────\ninterface BridgeOptions {\n channel: Channel;\n timeout?: number | null;\n callbackName?: string; // ← nuevo\n}\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout> | null;\n}\n\ninterface Channel {\n postMessage: (message: string) => void;\n}\n\n\n\n// ─── Clase ──────────────────────────────────────────────\n\nexport default class NativeBridge {\n private _pending = new Map<number, PendingCall>();\n private _callId = 0;\n private readonly _defaultTimeout: number | null;\n private readonly _channel: Channel;\n\n\n constructor({ channel, timeout = 3000, callbackName = '__nativeResponseHandler' }: BridgeOptions) {\n this._defaultTimeout = timeout;\n this._channel = channel;\n\n if (!this._channel) {\n throw new Error('Channel not found');\n }\n\n (window as any)[callbackName] = (id: number, error: any, result: any) => {\n this._settlePendingCall(id, error, result);\n };\n\n // Proxy: cualquier propiedad no existente se convierte en call()\n return new Proxy(this, {\n get(target: NativeBridge, prop: string | symbol) {\n if (prop in target) {\n return (target as any)[prop];\n }\n return (data?: unknown, timeout?: number | null) => target.call(String(prop), data, timeout);\n },\n }) as unknown as NativeBridge;\n }\n\n\n private _settlePendingCall(id: number, error: any, result: any) {\n\n const pending = this._pending.get(id);\n if (!pending) {\n return;\n }\n\n if (pending.timer !== null) {\n clearTimeout(pending.timer);\n }\n\n this._pending.delete(id);\n\n if (error) {\n pending.reject(error instanceof Error? error : new Error(String(error)));\n } else {\n pending.resolve(result);\n }\n }\n\n call(method: string, data: unknown = null, timeout?: number | null): Promise<unknown> {\n\n\n const effectiveTimeout = timeout !== undefined ? timeout : this._defaultTimeout;\n\n return new Promise<unknown>((resolve, reject) => {\n const id = this._callId++;\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n // Solo crear timer si hay timeout\n if (effectiveTimeout !== null && effectiveTimeout > 0) {\n timer = setTimeout(() => {\n this._pending.delete(id);\n reject(new Error(`Timeout (${effectiveTimeout}ms): ${method}`));\n }, effectiveTimeout);\n }\n\n this._pending.set(id, { resolve, reject, timer });\n this._channel!.postMessage(JSON.stringify({ id, method, data }));\n });\n }\n\n\n send(method: string, data: unknown = null): void {\n this._channel!.postMessage(JSON.stringify({ method, data }));\n }\n\n /**\n * Número de llamadas pendientes\n */\n get pendingCount(): number {\n return this._pending.size;\n }\n\n /**\n * Cancela todas las llamadas pendientes\n */\n cancelAll(): void {\n for (const [, { reject, timer }] of this._pending) {\n if (timer !== null) {\n clearTimeout(timer);\n }\n reject(new Error('Cancelled'));\n }\n this._pending.clear();\n }\n}"]}
@@ -5,8 +5,14 @@ export default class CancellablePromise<T> extends Promise<T> {
5
5
  constructor(executor: CancellablePromiseExecutor<T>);
6
6
  get cancelled(): boolean;
7
7
  cancel(reason?: unknown): void;
8
- static compete<T>(promises: CancellablePromise<T>[]): Promise<T>;
9
- static cooperate<T>(promises: CancellablePromise<T>[]): Promise<T[]>;
8
+ /**
9
+ * Resolves or rejects as the first of the promises to settle (Promise.race), and cancels all the others, also when
10
+ * the first one fails.
11
+ * @throws {Error} When there are no promises.
12
+ */
13
+ static raceAndCancelOthers<T>(promises: CancellablePromise<T>[]): Promise<T>;
14
+ /** Resolves with all the results (Promise.all); when one fails, cancels all of them and rejects with its error. */
15
+ static allOrCancelAll<T>(promises: CancellablePromise<T>[]): Promise<T[]>;
10
16
  static withTimeout<T>(executor: CancellablePromiseExecutor<T>, ms: number): CancellablePromise<T>;
11
17
  }
12
18
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"cancellable-promise.d.ts","sourceRoot":"","sources":["../src/cancellable-promise.ts"],"names":[],"mappings":"AAAA,KAAK,0BAA0B,CAAC,CAAC,IAAI,CACjC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,EAClC,MAAM,EAAE,WAAW,KAClB,IAAI,CAAC;AAEV,MAAM,CAAC,OAAO,OAAO,kBAAkB,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IAEzD,OAAO,CAAC,WAAW,CAAkB;IAErC,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,uBAE1B;gBAEW,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAcnD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,MAAM,CAAC,MAAM,GAAE,OAAwC,GAAG,IAAI;WAMjD,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;WAyBzD,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAW1E,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC;CA4BpG"}
1
+ {"version":3,"file":"cancellable-promise.d.ts","sourceRoot":"","sources":["../src/cancellable-promise.ts"],"names":[],"mappings":"AAAA,KAAK,0BAA0B,CAAC,CAAC,IAAI,CACjC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,EAClC,MAAM,EAAE,WAAW,KAClB,IAAI,CAAC;AAEV,MAAM,CAAC,OAAO,OAAO,kBAAkB,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IAEzD,OAAO,CAAC,WAAW,CAAkB;IAErC,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,uBAE1B;gBAEW,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAcnD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,MAAM,CAAC,MAAM,GAAE,OAAwC,GAAG,IAAI;IAM9D;;;;OAIG;WACU,mBAAmB,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAyBlF,mHAAmH;WACtG,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAW/E,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC;CA4BpG"}
@@ -20,9 +20,14 @@ export default class CancellablePromise extends Promise {
20
20
  this._controller.abort(reason);
21
21
  }
22
22
  }
23
- static async compete(promises) {
23
+ /**
24
+ * Resolves or rejects as the first of the promises to settle (Promise.race), and cancels all the others, also when
25
+ * the first one fails.
26
+ * @throws {Error} When there are no promises.
27
+ */
28
+ static async raceAndCancelOthers(promises) {
24
29
  if (promises.length === 0) {
25
- throw new Error("No promises to compete.");
30
+ throw new Error("No promises to race.");
26
31
  }
27
32
  const result = await Promise.race(promises.map((promise, index) => promise.then(value => ({ index, value, rejected: false }), reason => ({ index, reason, rejected: true }))));
28
33
  for (let i = 0; i < promises.length; i++) {
@@ -35,7 +40,8 @@ export default class CancellablePromise extends Promise {
35
40
  }
36
41
  return result.value;
37
42
  }
38
- static async cooperate(promises) {
43
+ /** Resolves with all the results (Promise.all); when one fails, cancels all of them and rejects with its error. */
44
+ static async allOrCancelAll(promises) {
39
45
  try {
40
46
  return await Promise.all(promises);
41
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cancellable-promise.js","sourceRoot":"","sources":["../src/cancellable-promise.ts"],"names":[],"mappings":"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","sourcesContent":["type CancellablePromiseExecutor<T> = (\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n signal: AbortSignal\n) => void;\n\nexport default class CancellablePromise<T> extends Promise<T> {\n\n private _controller: AbortController;\n\n static get [Symbol.species]() {\n return Promise;\n }\n\n constructor(executor: CancellablePromiseExecutor<T>) {\n const controller = new AbortController();\n\n super((resolve, reject) => {\n controller.signal.addEventListener(\"abort\", () => {\n reject(controller.signal.reason);\n });\n\n executor(resolve, reject, controller.signal);\n });\n\n this._controller = controller;\n }\n\n get cancelled(): boolean {\n return this._controller.signal.aborted;\n }\n\n cancel(reason: unknown = new Error(\"Promesa cancelada\")): void {\n if (!this.cancelled) {\n this._controller.abort(reason);\n }\n }\n\n static async compete<T>(promises: CancellablePromise<T>[]): Promise<T> {\n if (promises.length === 0) {\n throw new Error(\"No promises to compete.\");\n }\n\n const result = await Promise.race(\n promises.map((promise, index) => promise.then(\n value => ({index, value, rejected: false as const}),\n reason => ({index, reason, rejected: true as const}),\n ))\n );\n\n for (let i = 0; i < promises.length; i++) {\n if (i !== result.index) {\n promises[i].cancel();\n }\n }\n\n if (result.rejected) {\n throw result.reason;\n }\n\n return result.value;\n }\n\n static async cooperate<T>(promises: CancellablePromise<T>[]): Promise<T[]> {\n try {\n return await Promise.all(promises);\n } catch (error) {\n for (const p of promises) {\n p.cancel();\n }\n throw error;\n }\n }\n\n static withTimeout<T>(executor: CancellablePromiseExecutor<T>, ms: number): CancellablePromise<T> {\n return new CancellablePromise<T>((resolve, reject, signal) => {\n let settled = false;\n const timer = setTimeout(() => {\n safeReject(new Error(`Timeout: ${ms}ms`));\n }, ms);\n\n const cleanup = () => clearTimeout(timer);\n const safeResolve = (value: T | PromiseLike<T>) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const safeReject = (reason?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(reason);\n };\n\n signal.addEventListener(\"abort\", () => {\n settled = true;\n cleanup();\n }, {once: true});\n executor(safeResolve, safeReject, signal);\n });\n }\n}"]}
1
+ {"version":3,"file":"cancellable-promise.js","sourceRoot":"","sources":["../src/cancellable-promise.ts"],"names":[],"mappings":"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","sourcesContent":["type CancellablePromiseExecutor<T> = (\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n signal: AbortSignal\n) => void;\n\nexport default class CancellablePromise<T> extends Promise<T> {\n\n private _controller: AbortController;\n\n static get [Symbol.species]() {\n return Promise;\n }\n\n constructor(executor: CancellablePromiseExecutor<T>) {\n const controller = new AbortController();\n\n super((resolve, reject) => {\n controller.signal.addEventListener(\"abort\", () => {\n reject(controller.signal.reason);\n });\n\n executor(resolve, reject, controller.signal);\n });\n\n this._controller = controller;\n }\n\n get cancelled(): boolean {\n return this._controller.signal.aborted;\n }\n\n cancel(reason: unknown = new Error(\"Promesa cancelada\")): void {\n if (!this.cancelled) {\n this._controller.abort(reason);\n }\n }\n\n /**\n * Resolves or rejects as the first of the promises to settle (Promise.race), and cancels all the others, also when\n * the first one fails.\n * @throws {Error} When there are no promises.\n */\n static async raceAndCancelOthers<T>(promises: CancellablePromise<T>[]): Promise<T> {\n if (promises.length === 0) {\n throw new Error(\"No promises to race.\");\n }\n\n const result = await Promise.race(\n promises.map((promise, index) => promise.then(\n value => ({index, value, rejected: false as const}),\n reason => ({index, reason, rejected: true as const}),\n ))\n );\n\n for (let i = 0; i < promises.length; i++) {\n if (i !== result.index) {\n promises[i].cancel();\n }\n }\n\n if (result.rejected) {\n throw result.reason;\n }\n\n return result.value;\n }\n\n /** Resolves with all the results (Promise.all); when one fails, cancels all of them and rejects with its error. */\n static async allOrCancelAll<T>(promises: CancellablePromise<T>[]): Promise<T[]> {\n try {\n return await Promise.all(promises);\n } catch (error) {\n for (const p of promises) {\n p.cancel();\n }\n throw error;\n }\n }\n\n static withTimeout<T>(executor: CancellablePromiseExecutor<T>, ms: number): CancellablePromise<T> {\n return new CancellablePromise<T>((resolve, reject, signal) => {\n let settled = false;\n const timer = setTimeout(() => {\n safeReject(new Error(`Timeout: ${ms}ms`));\n }, ms);\n\n const cleanup = () => clearTimeout(timer);\n const safeResolve = (value: T | PromiseLike<T>) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const safeReject = (reason?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(reason);\n };\n\n signal.addEventListener(\"abort\", () => {\n settled = true;\n cleanup();\n }, {once: true});\n executor(safeResolve, safeReject, signal);\n });\n }\n}"]}
@@ -4,12 +4,12 @@ function isRecordParams(params) {
4
4
  !(params instanceof URLSearchParams) &&
5
5
  typeof params[Symbol.iterator] !== 'function';
6
6
  }
7
- function appendCleanValue(params, key, value) {
7
+ function appendNonNullishValues(params, key, value) {
8
8
  if (value === null || value === undefined)
9
9
  return;
10
10
  if (Array.isArray(value)) {
11
11
  for (const item of value) {
12
- appendCleanValue(params, key, item);
12
+ appendNonNullishValues(params, key, item);
13
13
  }
14
14
  return;
15
15
  }
@@ -24,7 +24,7 @@ export default class CleanURLSearchParams extends URLSearchParams {
24
24
  super();
25
25
  // Filtrar `null` y `undefined` antes de añadirlos a URLSearchParams
26
26
  for (const [key, value] of Object.entries(params)) {
27
- appendCleanValue(this, key, value);
27
+ appendNonNullishValues(this, key, value);
28
28
  }
29
29
  }
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"clean-url-search-params.js","sourceRoot":"","sources":["../src/clean-url-search-params.ts"],"names":[],"mappings":"AAEA,SAAS,cAAc,CAAC,MAAe;IACnC,OAAO,MAAM,KAAK,IAAI;QAClB,OAAO,MAAM,KAAK,QAAQ;QAC1B,CAAC,CAAC,MAAM,YAAY,eAAe,CAAC;QACpC,OAAQ,MAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC;AAC/D,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAuB,EAAE,GAAW,EAAE,KAAU;IACtE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAElD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;QACD,OAAO;IACX,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,eAAe;IAC7D,YAAY,MAAkC;QAC1C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,KAAK,CAAC,MAA2D,CAAC,CAAC;YACnE,OAAO;QACX,CAAC;QAED,KAAK,EAAE,CAAC;QAER,oEAAoE;QACpE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;CACJ","sourcesContent":["type CleanURLSearchParamsInput = string | URLSearchParams | string[][] | Record<string, any>;\n\nfunction isRecordParams(params: unknown): params is Record<string, any> {\n return params !== null &&\n typeof params === 'object' &&\n !(params instanceof URLSearchParams) &&\n typeof (params as any)[Symbol.iterator] !== 'function';\n}\n\nfunction appendCleanValue(params: URLSearchParams, key: string, value: any): void {\n if (value === null || value === undefined) return;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n appendCleanValue(params, key, item);\n }\n return;\n }\n\n params.append(key, String(value));\n}\n\nexport default class CleanURLSearchParams extends URLSearchParams {\n constructor(params?: CleanURLSearchParamsInput) {\n if (!isRecordParams(params)) {\n super(params as string | URLSearchParams | string[][] | undefined);\n return;\n }\n\n super();\n\n // Filtrar `null` y `undefined` antes de añadirlos a URLSearchParams\n for (const [key, value] of Object.entries(params)) {\n appendCleanValue(this, key, value);\n }\n }\n}"]}
1
+ {"version":3,"file":"clean-url-search-params.js","sourceRoot":"","sources":["../src/clean-url-search-params.ts"],"names":[],"mappings":"AAEA,SAAS,cAAc,CAAC,MAAe;IACnC,OAAO,MAAM,KAAK,IAAI;QAClB,OAAO,MAAM,KAAK,QAAQ;QAC1B,CAAC,CAAC,MAAM,YAAY,eAAe,CAAC;QACpC,OAAQ,MAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC;AAC/D,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAuB,EAAE,GAAW,EAAE,KAAU;IAC5E,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAElD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,sBAAsB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO;IACX,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,eAAe;IAC7D,YAAY,MAAkC;QAC1C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,KAAK,CAAC,MAA2D,CAAC,CAAC;YACnE,OAAO;QACX,CAAC;QAED,KAAK,EAAE,CAAC;QAER,oEAAoE;QACpE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,sBAAsB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;IACL,CAAC;CACJ","sourcesContent":["type CleanURLSearchParamsInput = string | URLSearchParams | string[][] | Record<string, any>;\n\nfunction isRecordParams(params: unknown): params is Record<string, any> {\n return params !== null &&\n typeof params === 'object' &&\n !(params instanceof URLSearchParams) &&\n typeof (params as any)[Symbol.iterator] !== 'function';\n}\n\nfunction appendNonNullishValues(params: URLSearchParams, key: string, value: any): void {\n if (value === null || value === undefined) return;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n appendNonNullishValues(params, key, item);\n }\n return;\n }\n\n params.append(key, String(value));\n}\n\nexport default class CleanURLSearchParams extends URLSearchParams {\n constructor(params?: CleanURLSearchParamsInput) {\n if (!isRecordParams(params)) {\n super(params as string | URLSearchParams | string[][] | undefined);\n return;\n }\n\n super();\n\n // Filtrar `null` y `undefined` antes de añadirlos a URLSearchParams\n for (const [key, value] of Object.entries(params)) {\n appendNonNullishValues(this, key, value);\n }\n }\n}"]}