@vielzeug/toolkit 1.0.13 → 1.1.2

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 (141) hide show
  1. package/dist/array/{sortBy.cjs → arrange.cjs} +2 -2
  2. package/dist/array/arrange.cjs.map +1 -0
  3. package/dist/array/arrange.js +6 -0
  4. package/dist/array/arrange.js.map +1 -0
  5. package/dist/array/chunk.cjs.map +1 -1
  6. package/dist/array/chunk.js.map +1 -1
  7. package/dist/array/list.cjs +1 -1
  8. package/dist/array/list.cjs.map +1 -1
  9. package/dist/array/list.js +86 -53
  10. package/dist/array/list.js.map +1 -1
  11. package/dist/array/remoteList.cjs +2 -0
  12. package/dist/array/remoteList.cjs.map +1 -0
  13. package/dist/array/remoteList.js +123 -0
  14. package/dist/array/remoteList.js.map +1 -0
  15. package/dist/async/attempt.cjs.map +1 -0
  16. package/dist/async/attempt.js.map +1 -0
  17. package/dist/async/defer.cjs +2 -0
  18. package/dist/async/defer.cjs.map +1 -0
  19. package/dist/async/defer.js +10 -0
  20. package/dist/async/defer.js.map +1 -0
  21. package/dist/async/delay.cjs.map +1 -0
  22. package/dist/async/delay.js.map +1 -0
  23. package/dist/async/parallel.cjs +2 -0
  24. package/dist/async/parallel.cjs.map +1 -0
  25. package/dist/async/parallel.js +28 -0
  26. package/dist/async/parallel.js.map +1 -0
  27. package/dist/async/pool.cjs +2 -0
  28. package/dist/async/pool.cjs.map +1 -0
  29. package/dist/async/pool.js +22 -0
  30. package/dist/async/pool.js.map +1 -0
  31. package/dist/async/predict.cjs.map +1 -0
  32. package/dist/async/predict.js.map +1 -0
  33. package/dist/async/queue.cjs +2 -0
  34. package/dist/async/queue.cjs.map +1 -0
  35. package/dist/async/queue.js +57 -0
  36. package/dist/async/queue.js.map +1 -0
  37. package/dist/async/race.cjs +2 -0
  38. package/dist/async/race.cjs.map +1 -0
  39. package/dist/async/race.js +8 -0
  40. package/dist/async/race.js.map +1 -0
  41. package/dist/async/retry.cjs.map +1 -0
  42. package/dist/{function → async}/retry.js +4 -4
  43. package/dist/async/retry.js.map +1 -0
  44. package/dist/async/sleep.cjs +2 -0
  45. package/dist/async/sleep.cjs.map +1 -0
  46. package/dist/{function → async}/sleep.js +1 -1
  47. package/dist/async/sleep.js.map +1 -0
  48. package/dist/async/waitFor.cjs +2 -0
  49. package/dist/async/waitFor.cjs.map +1 -0
  50. package/dist/async/waitFor.js +37 -0
  51. package/dist/async/waitFor.js.map +1 -0
  52. package/dist/date/expires.cjs.map +1 -1
  53. package/dist/date/expires.js.map +1 -1
  54. package/dist/date/interval.cjs.map +1 -1
  55. package/dist/date/interval.js.map +1 -1
  56. package/dist/date/timeDiff.cjs.map +1 -1
  57. package/dist/date/timeDiff.js.map +1 -1
  58. package/dist/function/memo.cjs.map +1 -1
  59. package/dist/function/memo.js.map +1 -1
  60. package/dist/function/proxy.cjs.map +1 -1
  61. package/dist/function/proxy.js.map +1 -1
  62. package/dist/function/prune.cjs +2 -0
  63. package/dist/function/prune.cjs.map +1 -0
  64. package/dist/function/prune.js +30 -0
  65. package/dist/function/prune.js.map +1 -0
  66. package/dist/index.cjs +1 -1
  67. package/dist/index.d.ts +575 -51
  68. package/dist/index.js +242 -206
  69. package/dist/index.js.map +1 -1
  70. package/dist/logit/dist/logit.cjs +1 -1
  71. package/dist/logit/dist/logit.cjs.map +1 -1
  72. package/dist/logit/dist/logit.js +147 -64
  73. package/dist/logit/dist/logit.js.map +1 -1
  74. package/dist/math/abs.cjs +2 -0
  75. package/dist/math/abs.cjs.map +1 -0
  76. package/dist/math/abs.js +7 -0
  77. package/dist/math/abs.js.map +1 -0
  78. package/dist/math/add.cjs +2 -0
  79. package/dist/math/add.cjs.map +1 -0
  80. package/dist/math/add.js +9 -0
  81. package/dist/math/add.js.map +1 -0
  82. package/dist/math/allocate.cjs +2 -0
  83. package/dist/math/allocate.cjs.map +1 -0
  84. package/dist/math/allocate.js +29 -0
  85. package/dist/math/allocate.js.map +1 -0
  86. package/dist/math/distribute.cjs +2 -0
  87. package/dist/math/distribute.cjs.map +1 -0
  88. package/dist/math/distribute.js +18 -0
  89. package/dist/math/distribute.js.map +1 -0
  90. package/dist/math/divide.cjs +2 -0
  91. package/dist/math/divide.cjs.map +1 -0
  92. package/dist/math/divide.js +11 -0
  93. package/dist/math/divide.js.map +1 -0
  94. package/dist/math/multiply.cjs +2 -0
  95. package/dist/math/multiply.cjs.map +1 -0
  96. package/dist/math/multiply.js +9 -0
  97. package/dist/math/multiply.js.map +1 -0
  98. package/dist/math/subtract.cjs +2 -0
  99. package/dist/math/subtract.cjs.map +1 -0
  100. package/dist/math/subtract.js +9 -0
  101. package/dist/math/subtract.js.map +1 -0
  102. package/dist/money/currency.cjs +2 -0
  103. package/dist/money/currency.cjs.map +1 -0
  104. package/dist/money/currency.js +49 -0
  105. package/dist/money/currency.js.map +1 -0
  106. package/dist/money/exchange.cjs +2 -0
  107. package/dist/money/exchange.cjs.map +1 -0
  108. package/dist/money/exchange.js +13 -0
  109. package/dist/money/exchange.js.map +1 -0
  110. package/dist/object/cache.cjs +2 -0
  111. package/dist/object/cache.cjs.map +1 -0
  112. package/dist/object/cache.js +63 -0
  113. package/dist/object/cache.js.map +1 -0
  114. package/dist/object/merge.cjs.map +1 -1
  115. package/dist/object/merge.js.map +1 -1
  116. package/dist/object/parseJSON.cjs.map +1 -1
  117. package/dist/object/parseJSON.js.map +1 -1
  118. package/dist/object/path.cjs.map +1 -1
  119. package/dist/object/path.js.map +1 -1
  120. package/package.json +1 -1
  121. package/dist/array/sortBy.cjs.map +0 -1
  122. package/dist/array/sortBy.js +0 -6
  123. package/dist/array/sortBy.js.map +0 -1
  124. package/dist/function/attempt.cjs.map +0 -1
  125. package/dist/function/attempt.js.map +0 -1
  126. package/dist/function/delay.cjs.map +0 -1
  127. package/dist/function/delay.js.map +0 -1
  128. package/dist/function/predict.cjs.map +0 -1
  129. package/dist/function/predict.js.map +0 -1
  130. package/dist/function/retry.cjs.map +0 -1
  131. package/dist/function/retry.js.map +0 -1
  132. package/dist/function/sleep.cjs +0 -2
  133. package/dist/function/sleep.cjs.map +0 -1
  134. package/dist/function/sleep.js.map +0 -1
  135. /package/dist/{function → async}/attempt.cjs +0 -0
  136. /package/dist/{function → async}/attempt.js +0 -0
  137. /package/dist/{function → async}/delay.cjs +0 -0
  138. /package/dist/{function → async}/delay.js +0 -0
  139. /package/dist/{function → async}/predict.cjs +0 -0
  140. /package/dist/{function → async}/predict.js +0 -0
  141. /package/dist/{function → async}/retry.cjs +0 -0
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../function/compareBy.cjs"),o=(r,e)=>[...r].sort(t.compareBy(e));exports.sortBy=o;
2
- //# sourceMappingURL=sortBy.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../function/compareBy.cjs"),o=(r,e)=>[...r].sort(t.compareBy(e));exports.arrange=o;
2
+ //# sourceMappingURL=arrange.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrange.cjs","sources":["../../src/array/arrange.ts"],"sourcesContent":["import { compareBy } from '../function/compareBy';\n\n/**\n * Arranges (sorts) an array of objects based on multiple selectors.\n *\n * @example\n * ```ts\n * const data = [\n * { name: 'Alice', age: 30 },\n * { name: 'Bob', age: 25 },\n * { name: 'Charlie', age: 35 },\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 30 },\n * ].arrange(data, { name: 'asc', age: 'desc' }); // [ { name: 'Alice', age: 30 }, { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 35 }, { name: 'Charlie', age: 30 } ]\n * ```\n *\n * @param array - The array to sort.\n * @param selectors - An object where keys are the properties to sort by and values are 'asc' or 'desc'.\n * @returns A new sorted array.\n */\nexport const arrange = <T>(array: T[], selectors: Partial<Record<keyof T, 'asc' | 'desc'>>) => {\n return [...array].sort(compareBy(selectors));\n};\n"],"names":["arrange","array","selectors","compareBy"],"mappings":"6HAqBaA,EAAU,CAAIC,EAAYC,IAC9B,CAAC,GAAGD,CAAK,EAAE,KAAKE,EAAAA,UAAUD,CAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { compareBy as t } from "../function/compareBy.js";
2
+ const a = (r, o) => [...r].sort(t(o));
3
+ export {
4
+ a as arrange
5
+ };
6
+ //# sourceMappingURL=arrange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrange.js","sources":["../../src/array/arrange.ts"],"sourcesContent":["import { compareBy } from '../function/compareBy';\n\n/**\n * Arranges (sorts) an array of objects based on multiple selectors.\n *\n * @example\n * ```ts\n * const data = [\n * { name: 'Alice', age: 30 },\n * { name: 'Bob', age: 25 },\n * { name: 'Charlie', age: 35 },\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 30 },\n * ].arrange(data, { name: 'asc', age: 'desc' }); // [ { name: 'Alice', age: 30 }, { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 35 }, { name: 'Charlie', age: 30 } ]\n * ```\n *\n * @param array - The array to sort.\n * @param selectors - An object where keys are the properties to sort by and values are 'asc' or 'desc'.\n * @returns A new sorted array.\n */\nexport const arrange = <T>(array: T[], selectors: Partial<Record<keyof T, 'asc' | 'desc'>>) => {\n return [...array].sort(compareBy(selectors));\n};\n"],"names":["arrange","array","selectors","compareBy"],"mappings":";AAqBO,MAAMA,IAAU,CAAIC,GAAYC,MAC9B,CAAC,GAAGD,CAAK,EAAE,KAAKE,EAAUD,CAAS,CAAC;"}
@@ -1 +1 @@
1
- {"version":3,"file":"chunk.cjs","sources":["../../src/array/chunk.ts"],"sourcesContent":["import { assert } from '../function/assert';\nimport { isArray } from '../typed/isArray';\nimport { isString } from '../typed/isString';\n\ntype ChunkOptions = {\n overlap?: boolean;\n pad?: string;\n};\n\ntype ChunkResult<T> = (T extends string ? string : T[])[];\n\n/**\n * Splits an array or string into chunks of a specified size.\n *\n * @example\n * ```ts\n * chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]\n * chunk(\"hello\", 2) // [\"he\", \"ll\", \"o\"]\n * chunk(\"hello\", 2, { overlap: true }) // [\" h\", \"he\", \"el\", \"ll\", \"lo\", \"o \"]\n * ```\n *\n * @param input - The input array or string to be chunked.\n * @param size - The size of each chunk.\n * @param [options] - Additional options for chunking.\n * @param [options.overlap] -\n * @param [options.pad] -\n *\n * @returns An array of chunks.\n *\n * @throws {RangeError} If the chunk size is invalid.\n * @throws {TypeError} If the input type is invalid.\n */\nexport function chunk<T>(input: T[] | string, size = 2, options: ChunkOptions = {}): ChunkResult<T> {\n assert(isArray(input as T[]) || isString(input), 'Argument must be an array or string.', {\n args: { input },\n type: TypeError,\n });\n\n assert(size >= 1, 'Chunk size must be at least 1.', {\n args: { size },\n type: RangeError,\n });\n\n const { overlap = false, pad = ' ' } = options;\n\n if (isString(input) && overlap) {\n const padded = pad + input + pad;\n const numChunks = padded.length - size + 1;\n return Array.from({ length: numChunks }, (_, i) => padded.slice(i, i + size)) as ChunkResult<T>;\n }\n\n return Array.from({ length: Math.ceil(input.length / size) }, (_, i) =>\n input.slice(i * size, i * size + size),\n ) as ChunkResult<T>;\n}\n"],"names":["chunk","input","size","options","assert","isArray","isString","overlap","pad","padded","numChunks","_","i"],"mappings":"+LAgCO,SAASA,EAASC,EAAqBC,EAAO,EAAGC,EAAwB,CAAA,EAAoB,CAClGC,EAAAA,OAAOC,EAAAA,QAAQJ,CAAY,GAAKK,EAAAA,SAASL,CAAK,EAAG,uCAAwC,CACvF,KAAM,CAAE,MAAAA,CAAA,EACR,KAAM,SAAA,CACP,EAEDG,SAAOF,GAAQ,EAAG,iCAAkC,CAClD,KAAM,CAAE,KAAAA,CAAA,EACR,KAAM,UAAA,CACP,EAED,KAAM,CAAE,QAAAK,EAAU,GAAO,IAAAC,EAAM,KAAQL,EAEvC,GAAIG,EAAAA,SAASL,CAAK,GAAKM,EAAS,CAC9B,MAAME,EAASD,EAAMP,EAAQO,EACvBE,EAAYD,EAAO,OAASP,EAAO,EACzC,OAAO,MAAM,KAAK,CAAE,OAAQQ,GAAa,CAACC,EAAGC,IAAMH,EAAO,MAAMG,EAAGA,EAAIV,CAAI,CAAC,CAC9E,CAEA,OAAO,MAAM,KAAK,CAAE,OAAQ,KAAK,KAAKD,EAAM,OAASC,CAAI,CAAA,EAAK,CAACS,EAAGC,IAChEX,EAAM,MAAMW,EAAIV,EAAMU,EAAIV,EAAOA,CAAI,CAAA,CAEzC"}
1
+ {"version":3,"file":"chunk.cjs","sources":["../../src/array/chunk.ts"],"sourcesContent":["import { assert } from '../function/assert';\nimport { isArray } from '../typed/isArray';\nimport { isString } from '../typed/isString';\n\n// #region ChunkTypes\ntype ChunkOptions = {\n overlap?: boolean;\n pad?: string;\n};\n\ntype ChunkResult<T> = (T extends string ? string : T[])[];\n// #endregion ChunkTypes\n\n/**\n * Splits an array or string into chunks of a specified size.\n *\n * @example\n * ```ts\n * chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]\n * chunk(\"hello\", 2) // [\"he\", \"ll\", \"o\"]\n * chunk(\"hello\", 2, { overlap: true }) // [\" h\", \"he\", \"el\", \"ll\", \"lo\", \"o \"]\n * ```\n *\n * @param input - The input array or string to be chunked.\n * @param size - The size of each chunk.\n * @param [options] - Additional options for chunking.\n * @param [options.overlap] -\n * @param [options.pad] -\n *\n * @returns An array of chunks.\n *\n * @throws {RangeError} If the chunk size is invalid.\n * @throws {TypeError} If the input type is invalid.\n */\nexport function chunk<T>(input: T[] | string, size = 2, options: ChunkOptions = {}): ChunkResult<T> {\n assert(isArray(input as T[]) || isString(input), 'Argument must be an array or string.', {\n args: { input },\n type: TypeError,\n });\n\n assert(size >= 1, 'Chunk size must be at least 1.', {\n args: { size },\n type: RangeError,\n });\n\n const { overlap = false, pad = ' ' } = options;\n\n if (isString(input) && overlap) {\n const padded = pad + input + pad;\n const numChunks = padded.length - size + 1;\n return Array.from({ length: numChunks }, (_, i) => padded.slice(i, i + size)) as ChunkResult<T>;\n }\n\n return Array.from({ length: Math.ceil(input.length / size) }, (_, i) =>\n input.slice(i * size, i * size + size),\n ) as ChunkResult<T>;\n}\n"],"names":["chunk","input","size","options","assert","isArray","isString","overlap","pad","padded","numChunks","_","i"],"mappings":"+LAkCO,SAASA,EAASC,EAAqBC,EAAO,EAAGC,EAAwB,CAAA,EAAoB,CAClGC,EAAAA,OAAOC,EAAAA,QAAQJ,CAAY,GAAKK,EAAAA,SAASL,CAAK,EAAG,uCAAwC,CACvF,KAAM,CAAE,MAAAA,CAAA,EACR,KAAM,SAAA,CACP,EAEDG,SAAOF,GAAQ,EAAG,iCAAkC,CAClD,KAAM,CAAE,KAAAA,CAAA,EACR,KAAM,UAAA,CACP,EAED,KAAM,CAAE,QAAAK,EAAU,GAAO,IAAAC,EAAM,KAAQL,EAEvC,GAAIG,EAAAA,SAASL,CAAK,GAAKM,EAAS,CAC9B,MAAME,EAASD,EAAMP,EAAQO,EACvBE,EAAYD,EAAO,OAASP,EAAO,EACzC,OAAO,MAAM,KAAK,CAAE,OAAQQ,GAAa,CAACC,EAAGC,IAAMH,EAAO,MAAMG,EAAGA,EAAIV,CAAI,CAAC,CAC9E,CAEA,OAAO,MAAM,KAAK,CAAE,OAAQ,KAAK,KAAKD,EAAM,OAASC,CAAI,CAAA,EAAK,CAACS,EAAGC,IAChEX,EAAM,MAAMW,EAAIV,EAAMU,EAAIV,EAAOA,CAAI,CAAA,CAEzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chunk.js","sources":["../../src/array/chunk.ts"],"sourcesContent":["import { assert } from '../function/assert';\nimport { isArray } from '../typed/isArray';\nimport { isString } from '../typed/isString';\n\ntype ChunkOptions = {\n overlap?: boolean;\n pad?: string;\n};\n\ntype ChunkResult<T> = (T extends string ? string : T[])[];\n\n/**\n * Splits an array or string into chunks of a specified size.\n *\n * @example\n * ```ts\n * chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]\n * chunk(\"hello\", 2) // [\"he\", \"ll\", \"o\"]\n * chunk(\"hello\", 2, { overlap: true }) // [\" h\", \"he\", \"el\", \"ll\", \"lo\", \"o \"]\n * ```\n *\n * @param input - The input array or string to be chunked.\n * @param size - The size of each chunk.\n * @param [options] - Additional options for chunking.\n * @param [options.overlap] -\n * @param [options.pad] -\n *\n * @returns An array of chunks.\n *\n * @throws {RangeError} If the chunk size is invalid.\n * @throws {TypeError} If the input type is invalid.\n */\nexport function chunk<T>(input: T[] | string, size = 2, options: ChunkOptions = {}): ChunkResult<T> {\n assert(isArray(input as T[]) || isString(input), 'Argument must be an array or string.', {\n args: { input },\n type: TypeError,\n });\n\n assert(size >= 1, 'Chunk size must be at least 1.', {\n args: { size },\n type: RangeError,\n });\n\n const { overlap = false, pad = ' ' } = options;\n\n if (isString(input) && overlap) {\n const padded = pad + input + pad;\n const numChunks = padded.length - size + 1;\n return Array.from({ length: numChunks }, (_, i) => padded.slice(i, i + size)) as ChunkResult<T>;\n }\n\n return Array.from({ length: Math.ceil(input.length / size) }, (_, i) =>\n input.slice(i * size, i * size + size),\n ) as ChunkResult<T>;\n}\n"],"names":["chunk","input","size","options","assert","isArray","isString","overlap","pad","padded","numChunks","_","i"],"mappings":";;;AAgCO,SAASA,EAASC,GAAqBC,IAAO,GAAGC,IAAwB,CAAA,GAAoB;AAClG,EAAAC,EAAOC,EAAQJ,CAAY,KAAKK,EAASL,CAAK,GAAG,wCAAwC;AAAA,IACvF,MAAM,EAAE,OAAAA,EAAA;AAAA,IACR,MAAM;AAAA,EAAA,CACP,GAEDG,EAAOF,KAAQ,GAAG,kCAAkC;AAAA,IAClD,MAAM,EAAE,MAAAA,EAAA;AAAA,IACR,MAAM;AAAA,EAAA,CACP;AAED,QAAM,EAAE,SAAAK,IAAU,IAAO,KAAAC,IAAM,QAAQL;AAEvC,MAAIG,EAASL,CAAK,KAAKM,GAAS;AAC9B,UAAME,IAASD,IAAMP,IAAQO,GACvBE,IAAYD,EAAO,SAASP,IAAO;AACzC,WAAO,MAAM,KAAK,EAAE,QAAQQ,KAAa,CAACC,GAAGC,MAAMH,EAAO,MAAMG,GAAGA,IAAIV,CAAI,CAAC;AAAA,EAC9E;AAEA,SAAO,MAAM;AAAA,IAAK,EAAE,QAAQ,KAAK,KAAKD,EAAM,SAASC,CAAI,EAAA;AAAA,IAAK,CAACS,GAAGC,MAChEX,EAAM,MAAMW,IAAIV,GAAMU,IAAIV,IAAOA,CAAI;AAAA,EAAA;AAEzC;"}
1
+ {"version":3,"file":"chunk.js","sources":["../../src/array/chunk.ts"],"sourcesContent":["import { assert } from '../function/assert';\nimport { isArray } from '../typed/isArray';\nimport { isString } from '../typed/isString';\n\n// #region ChunkTypes\ntype ChunkOptions = {\n overlap?: boolean;\n pad?: string;\n};\n\ntype ChunkResult<T> = (T extends string ? string : T[])[];\n// #endregion ChunkTypes\n\n/**\n * Splits an array or string into chunks of a specified size.\n *\n * @example\n * ```ts\n * chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]\n * chunk(\"hello\", 2) // [\"he\", \"ll\", \"o\"]\n * chunk(\"hello\", 2, { overlap: true }) // [\" h\", \"he\", \"el\", \"ll\", \"lo\", \"o \"]\n * ```\n *\n * @param input - The input array or string to be chunked.\n * @param size - The size of each chunk.\n * @param [options] - Additional options for chunking.\n * @param [options.overlap] -\n * @param [options.pad] -\n *\n * @returns An array of chunks.\n *\n * @throws {RangeError} If the chunk size is invalid.\n * @throws {TypeError} If the input type is invalid.\n */\nexport function chunk<T>(input: T[] | string, size = 2, options: ChunkOptions = {}): ChunkResult<T> {\n assert(isArray(input as T[]) || isString(input), 'Argument must be an array or string.', {\n args: { input },\n type: TypeError,\n });\n\n assert(size >= 1, 'Chunk size must be at least 1.', {\n args: { size },\n type: RangeError,\n });\n\n const { overlap = false, pad = ' ' } = options;\n\n if (isString(input) && overlap) {\n const padded = pad + input + pad;\n const numChunks = padded.length - size + 1;\n return Array.from({ length: numChunks }, (_, i) => padded.slice(i, i + size)) as ChunkResult<T>;\n }\n\n return Array.from({ length: Math.ceil(input.length / size) }, (_, i) =>\n input.slice(i * size, i * size + size),\n ) as ChunkResult<T>;\n}\n"],"names":["chunk","input","size","options","assert","isArray","isString","overlap","pad","padded","numChunks","_","i"],"mappings":";;;AAkCO,SAASA,EAASC,GAAqBC,IAAO,GAAGC,IAAwB,CAAA,GAAoB;AAClG,EAAAC,EAAOC,EAAQJ,CAAY,KAAKK,EAASL,CAAK,GAAG,wCAAwC;AAAA,IACvF,MAAM,EAAE,OAAAA,EAAA;AAAA,IACR,MAAM;AAAA,EAAA,CACP,GAEDG,EAAOF,KAAQ,GAAG,kCAAkC;AAAA,IAClD,MAAM,EAAE,MAAAA,EAAA;AAAA,IACR,MAAM;AAAA,EAAA,CACP;AAED,QAAM,EAAE,SAAAK,IAAU,IAAO,KAAAC,IAAM,QAAQL;AAEvC,MAAIG,EAASL,CAAK,KAAKM,GAAS;AAC9B,UAAME,IAASD,IAAMP,IAAQO,GACvBE,IAAYD,EAAO,SAASP,IAAO;AACzC,WAAO,MAAM,KAAK,EAAE,QAAQQ,KAAa,CAACC,GAAGC,MAAMH,EAAO,MAAMG,GAAGA,IAAIV,CAAI,CAAC;AAAA,EAC9E;AAEA,SAAO,MAAM;AAAA,IAAK,EAAE,QAAQ,KAAK,KAAKD,EAAM,SAASC,CAAI,EAAA;AAAA,IAAK,CAACS,GAAGC,MAChEX,EAAM,MAAMW,IAAIV,GAAMU,IAAIV,IAAOA,CAAI;AAAA,EAAA;AAEzC;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("../function/debounce.cjs"),d=require("./chunk.cjs"),x=require("./search.cjs"),T=10,b=.5,y=1;function f(s,i,r){const a=r?[...s].sort(r):[...s];return d.chunk(a,i)}function m(s,i,r=""){return(r?x.search(s,r,b):s).filter(i)}function D(s,i={}){let{limit:r=T,filterFn:a=()=>!0,sortFn:o}=i,c=[...s],t=0,h="",l=m(c,a),n=f(l,r,o);const u=()=>{l=m(c,a,h),n=f(l,r,o);const e=Math.max(0,n.length-1);return t=Math.max(0,Math.min(t,e)),n[t]??[]};return{get current(){return n[t]??[]},set data(e){c=[...e],t=0,u()},filter(e){return a=e,t=0,u()},set limit(e){r=Math.max(y,e),u()},get meta(){return{end:Math.min(r*(t+1),l.length),isEmpty:l.length===0,isFirst:t===0,isLast:t===n.length-1,limit:r,page:t+1,pages:Math.ceil(l.length/r),start:Math.max(0,r*t+1),total:l.length}},next(){t<n.length-1&&t++},set page(e){const g=e-1,M=g<0?n.length+g:g;t=Math.max(0,Math.min(M,n.length-1))},get pages(){return n},prev(){t>0&&t--},reset(){return t=0,h="",a=i.filterFn??(()=>!0),u()},search:p.debounce(e=>(h=e,u())),sort(e){return o=e,u()},*[Symbol.iterator](){for(const e of n)yield e}}}exports.list=D;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Q=require("./search.cjs");function j(S,i={}){const T=new Set,M={debounceMs:300,limit:10,searchTone:.5};let x=[...S],n=Math.max(1,i.limit??M.limit),m=i.filterFn??(()=>!0),u=i.sortFn;const y=i.searchFn??((t,e,o)=>Q.search([...t],e,o)),v=i.searchTone??M.searchTone;let c="",s=0,h=[];const d=()=>{for(const t of T)t()},g=()=>{let t=x;c&&(t=y(t,c,v)),m&&(t=t.filter(m)),t=u?[...t].sort(u):[...t];const e=Math.max(1,Math.ceil(t.length/n));s=Math.min(s,e-1),h=t},D=()=>{if(!h.length)return[];const t=s*n;return h.slice(t,t+n)},r=()=>{g(),d()};let F;const L=(t,e)=>{F&&clearTimeout(F),F=setTimeout(()=>{c=t,F=void 0,r()},e)};return g(),{batch(t){let e=n,o=m,l=u,f=c,b=x,p=s;const w=(a,E,O)=>Math.max(0,Math.min(a,Math.max(0,Math.ceil(E/O)-1)));t({goTo:a=>{p=w(a-1,h.length,e)},setData:a=>{b=[...a],p=0},setFilter:a=>{o=a},setLimit:a=>{e=Math.max(1,a)},setQuery:a=>{f=a,p=0},setSort:a=>{l=a}}),n=e,m=o,u=l,c=f,x=b,s=p,r()},get current(){return D()},goTo(t){const e=Math.max(1,Math.ceil(h.length/n));s=Math.max(0,Math.min(t-1,e-1)),d()},get meta(){const t=h.length,e=Math.max(1,Math.ceil(t/n)),o=t===0,l=Math.min(s+1,e),f=o?0:(l-1)*n+1;return{end:o?0:Math.min(l*n,t),isEmpty:o,isFirst:l<=1,isLast:l>=e,limit:n,page:l,pages:e,start:f,total:t}},next(){const t=Math.max(1,Math.ceil(h.length/n));s<t-1&&(s++,d())},prev(){s>0&&(s--,d())},reset(){n=Math.max(1,i.limit??M.limit),m=i.filterFn??(()=>!0),u=i.sortFn,c="",s=0,r()},search(t,e){c=t,s=0,e?.immediate?r():L(t,i.debounceMs??M.debounceMs)},setData(t){x=[...t],s=0,r()},setFilter(t){m=t,s=0,r()},setLimit(t){n=Math.max(1,t),s=0,r()},setSort(t){u=t,r()},subscribe(t){return T.add(t),()=>T.delete(t)}}}exports.list=j;
2
2
  //# sourceMappingURL=list.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.cjs","sources":["../../src/array/list.ts"],"sourcesContent":["import { debounce } from '../function/debounce';\nimport type { Predicate } from '../types';\nimport { chunk } from './chunk';\nimport { search } from './search';\n\ntype Config<T> = {\n filterFn?: Predicate<T>;\n limit?: number;\n sortFn?: (a: T, b: T) => number;\n};\n\nconst DEFAULT_LIMIT = 10;\nconst DEFAULT_SEARCH_TONE = 0.5;\nconst MIN_LIMIT = 1;\n\nfunction getPages<T>(data: T[], size: number, sortFn: Config<T>['sortFn']): T[][] {\n const sortedData = sortFn ? [...data].sort(sortFn) : [...data];\n return chunk<T>(sortedData, size) as T[][];\n}\n\nfunction getData<T>(data: T[], currentFilterFn: Predicate<T>, query = ''): T[] {\n const searchResults = query ? search(data, query, DEFAULT_SEARCH_TONE) : data;\n return searchResults.filter(currentFilterFn) as T[];\n}\n\nexport function list<T>(initialData: T[], config: Config<T> = {}) {\n let { limit = DEFAULT_LIMIT, filterFn = () => true, sortFn } = config;\n let rawData = [...initialData];\n let offset = 0;\n let query = '';\n let data = getData(rawData, filterFn);\n let pages = getPages(data, limit, sortFn);\n\n const update = () => {\n data = getData(rawData, filterFn, query);\n pages = getPages(data, limit, sortFn);\n // Ensure offset is valid for the new page count\n // If pages is empty, offset should be 0. Max index is pages.length - 1\n const maxOffset = Math.max(0, pages.length - 1);\n offset = Math.max(0, Math.min(offset, maxOffset));\n return pages[offset] ?? [];\n };\n\n return {\n get current() {\n return pages[offset] ?? [];\n },\n set data(newData: T[]) {\n rawData = [...newData];\n offset = 0;\n update();\n },\n filter(predicate: (item: T) => boolean) {\n filterFn = predicate;\n offset = 0;\n return update();\n },\n set limit(newLimit: number) {\n limit = Math.max(MIN_LIMIT, newLimit);\n update();\n },\n get meta() {\n return {\n end: Math.min(limit * (offset + 1), data.length),\n isEmpty: data.length === 0,\n isFirst: offset === 0,\n isLast: offset === pages.length - 1,\n limit: limit,\n page: offset + 1,\n pages: Math.ceil(data.length / limit),\n start: Math.max(0, limit * offset + 1),\n total: data.length,\n };\n },\n next() {\n if (offset < pages.length - 1) {\n offset++;\n }\n },\n set page(page: number) {\n const index = page - 1;\n const value = index < 0 ? pages.length + index : index;\n offset = Math.max(0, Math.min(value, pages.length - 1));\n },\n get pages() {\n return pages;\n },\n prev() {\n if (offset > 0) {\n offset--;\n }\n },\n reset() {\n offset = 0;\n query = '';\n filterFn = config.filterFn ?? (() => true);\n return update();\n },\n search: debounce((str: string) => {\n query = str;\n return update();\n }),\n sort(fn?: (a: T, b: T) => number) {\n sortFn = fn;\n return update();\n },\n *[Symbol.iterator]() {\n for (const page of pages) {\n yield page;\n }\n },\n };\n}\n"],"names":["DEFAULT_LIMIT","DEFAULT_SEARCH_TONE","MIN_LIMIT","getPages","data","size","sortFn","sortedData","chunk","getData","currentFilterFn","query","search","list","initialData","config","limit","filterFn","rawData","offset","pages","update","maxOffset","newData","predicate","newLimit","page","index","value","debounce","str","fn"],"mappings":"+KAWMA,EAAgB,GAChBC,EAAsB,GACtBC,EAAY,EAElB,SAASC,EAAYC,EAAWC,EAAcC,EAAoC,CAChF,MAAMC,EAAaD,EAAS,CAAC,GAAGF,CAAI,EAAE,KAAKE,CAAM,EAAI,CAAC,GAAGF,CAAI,EAC7D,OAAOI,EAAAA,MAASD,EAAYF,CAAI,CAClC,CAEA,SAASI,EAAWL,EAAWM,EAA+BC,EAAQ,GAAS,CAE7E,OADsBA,EAAQC,EAAAA,OAAOR,EAAMO,EAAOV,CAAmB,EAAIG,GACpD,OAAOM,CAAe,CAC7C,CAEO,SAASG,EAAQC,EAAkBC,EAAoB,GAAI,CAChE,GAAI,CAAE,MAAAC,EAAQhB,EAAe,SAAAiB,EAAW,IAAM,GAAM,OAAAX,GAAWS,EAC3DG,EAAU,CAAC,GAAGJ,CAAW,EACzBK,EAAS,EACTR,EAAQ,GACRP,EAAOK,EAAQS,EAASD,CAAQ,EAChCG,EAAQjB,EAASC,EAAMY,EAAOV,CAAM,EAExC,MAAMe,EAAS,IAAM,CACnBjB,EAAOK,EAAQS,EAASD,EAAUN,CAAK,EACvCS,EAAQjB,EAASC,EAAMY,EAAOV,CAAM,EAGpC,MAAMgB,EAAY,KAAK,IAAI,EAAGF,EAAM,OAAS,CAAC,EAC9C,OAAAD,EAAS,KAAK,IAAI,EAAG,KAAK,IAAIA,EAAQG,CAAS,CAAC,EACzCF,EAAMD,CAAM,GAAK,CAAA,CAC1B,EAEA,MAAO,CACL,IAAI,SAAU,CACZ,OAAOC,EAAMD,CAAM,GAAK,CAAA,CAC1B,EACA,IAAI,KAAKI,EAAc,CACrBL,EAAU,CAAC,GAAGK,CAAO,EACrBJ,EAAS,EACTE,EAAA,CACF,EACA,OAAOG,EAAiC,CACtC,OAAAP,EAAWO,EACXL,EAAS,EACFE,EAAA,CACT,EACA,IAAI,MAAMI,EAAkB,CAC1BT,EAAQ,KAAK,IAAId,EAAWuB,CAAQ,EACpCJ,EAAA,CACF,EACA,IAAI,MAAO,CACT,MAAO,CACL,IAAK,KAAK,IAAIL,GAASG,EAAS,GAAIf,EAAK,MAAM,EAC/C,QAASA,EAAK,SAAW,EACzB,QAASe,IAAW,EACpB,OAAQA,IAAWC,EAAM,OAAS,EAClC,MAAAJ,EACA,KAAMG,EAAS,EACf,MAAO,KAAK,KAAKf,EAAK,OAASY,CAAK,EACpC,MAAO,KAAK,IAAI,EAAGA,EAAQG,EAAS,CAAC,EACrC,MAAOf,EAAK,MAAA,CAEhB,EACA,MAAO,CACDe,EAASC,EAAM,OAAS,GAC1BD,GAEJ,EACA,IAAI,KAAKO,EAAc,CACrB,MAAMC,EAAQD,EAAO,EACfE,EAAQD,EAAQ,EAAIP,EAAM,OAASO,EAAQA,EACjDR,EAAS,KAAK,IAAI,EAAG,KAAK,IAAIS,EAAOR,EAAM,OAAS,CAAC,CAAC,CACxD,EACA,IAAI,OAAQ,CACV,OAAOA,CACT,EACA,MAAO,CACDD,EAAS,GACXA,GAEJ,EACA,OAAQ,CACN,OAAAA,EAAS,EACTR,EAAQ,GACRM,EAAWF,EAAO,WAAa,IAAM,IAC9BM,EAAA,CACT,EACA,OAAQQ,EAAAA,SAAUC,IAChBnB,EAAQmB,EACDT,EAAA,EACR,EACD,KAAKU,EAA6B,CAChC,OAAAzB,EAASyB,EACFV,EAAA,CACT,EACA,EAAE,OAAO,QAAQ,GAAI,CACnB,UAAWK,KAAQN,EACjB,MAAMM,CAEV,CAAA,CAEJ"}
1
+ {"version":3,"file":"list.cjs","sources":["../../src/array/list.ts"],"sourcesContent":["import type { Predicate, Sorter } from '../types';\nimport { search as defaultSearch } from './search';\n\n// #region Meta\nexport type Meta = Readonly<{\n end: number; // inclusive\n isEmpty: boolean;\n isFirst: boolean;\n isLast: boolean;\n limit: number;\n page: number; // 1-based\n pages: number;\n start: number; // 1-based\n total: number;\n}>;\n// #endregion Meta\n\n// #region List\nexport type List<T, F, S> = {\n readonly current: readonly T[];\n readonly meta: Meta;\n subscribe(listener: () => void): () => void;\n\n goTo(page: number): void;\n next(): void;\n prev(): void;\n reset(): void;\n search(query: string, opts?: { immediate?: boolean }): void;\n setData?(data: readonly T[]): void; // implemented by local\n setFilter(filter: F): void;\n setLimit(n: number): void;\n setSort(sort?: S): void;\n\n // Batch updates across properties in one recompute/refetch\n batch(\n mutator: (ctx: {\n setLimit(n: number): void;\n setFilter(f: F): void;\n setSort(s?: S): void;\n setQuery(q: string): void;\n setData?(d: readonly T[]): void; // local-only\n goTo(p: number): void; // 1-based\n }) => void,\n ): void;\n};\n// #endregion List\n\n// #region LocalConfig\ntype LocalConfig<T> = Readonly<{\n debounceMs?: number;\n filterFn?: Predicate<T>;\n limit?: number;\n searchFn?: (items: readonly T[], query: string, tone: number) => readonly T[];\n searchTone?: number;\n sortFn?: Sorter<T>;\n}>;\n// #endregion LocalConfig\n\nexport function list<T>(initialData: readonly T[], cfg: LocalConfig<T> = {}): List<T, Predicate<T>, Sorter<T>> {\n const listeners = new Set<() => void>();\n\n const DEFAULTS = { debounceMs: 300, limit: 10, searchTone: 0.5 } as const;\n\n let rawData: readonly T[] = [...initialData];\n let limit = Math.max(1, cfg.limit ?? DEFAULTS.limit);\n let filterFn: Predicate<T> = cfg.filterFn ?? (() => true);\n let sortFn: Sorter<T> | undefined = cfg.sortFn;\n const searchFn = cfg.searchFn ?? ((items: readonly T[], q: string, t: number) => defaultSearch([...items], q, t));\n const searchTone = cfg.searchTone ?? DEFAULTS.searchTone;\n\n let query = '';\n let offset = 0;\n let view: readonly T[] = [];\n\n const notify = () => {\n for (const l of listeners) {\n l();\n }\n };\n\n const recompute = () => {\n let arr = rawData;\n\n if (query) arr = searchFn(arr, query, searchTone);\n if (filterFn) arr = arr.filter(filterFn);\n arr = sortFn ? [...arr].sort(sortFn) : [...arr];\n\n const pages = Math.max(1, Math.ceil(arr.length / limit));\n offset = Math.min(offset, pages - 1);\n view = arr;\n };\n\n const slice = (): readonly T[] => {\n if (!view.length) return [];\n const start = offset * limit;\n return view.slice(start, start + limit);\n };\n\n const update = () => {\n recompute();\n notify();\n };\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const debouncedSearch = (q: string, ms: number) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n query = q;\n timer = undefined;\n void update();\n }, ms);\n };\n\n // initial compute\n recompute();\n\n return {\n batch(mutator) {\n let nextLimit = limit;\n let nextFilter = filterFn;\n let nextSort = sortFn;\n let nextQuery = query;\n let nextData = rawData;\n let nextOffset = offset;\n\n const clamp = (i: number, total: number, lim: number) =>\n Math.max(0, Math.min(i, Math.max(0, Math.ceil(total / lim) - 1)));\n\n mutator({\n goTo: (p) => {\n nextOffset = clamp(p - 1, view.length, nextLimit);\n },\n setData: (d) => {\n nextData = [...d];\n nextOffset = 0;\n },\n setFilter: (f) => {\n nextFilter = f;\n },\n setLimit: (n) => {\n nextLimit = Math.max(1, n);\n },\n setQuery: (q) => {\n nextQuery = q;\n nextOffset = 0;\n },\n setSort: (s) => {\n nextSort = s;\n },\n });\n\n // apply once\n limit = nextLimit;\n filterFn = nextFilter;\n sortFn = nextSort;\n query = nextQuery;\n rawData = nextData;\n offset = nextOffset;\n\n update();\n },\n get current() {\n return slice();\n },\n goTo(page) {\n const pages = Math.max(1, Math.ceil(view.length / limit));\n offset = Math.max(0, Math.min(page - 1, pages - 1));\n notify();\n },\n get meta() {\n const total = view.length;\n const pages = Math.max(1, Math.ceil(total / limit));\n const isEmpty = total === 0;\n const page = Math.min(offset + 1, pages);\n const start = isEmpty ? 0 : (page - 1) * limit + 1;\n const end = isEmpty ? 0 : Math.min(page * limit, total);\n return {\n end,\n isEmpty,\n isFirst: page <= 1,\n isLast: page >= pages,\n limit,\n page,\n pages,\n start,\n total,\n };\n },\n next() {\n const pages = Math.max(1, Math.ceil(view.length / limit));\n if (offset < pages - 1) {\n offset++;\n notify();\n }\n },\n prev() {\n if (offset > 0) {\n offset--;\n notify();\n }\n },\n reset() {\n limit = Math.max(1, cfg.limit ?? DEFAULTS.limit);\n filterFn = cfg.filterFn ?? (() => true);\n sortFn = cfg.sortFn;\n query = '';\n offset = 0;\n update();\n },\n search(q, opts) {\n query = q;\n offset = 0;\n if (opts?.immediate) {\n update();\n } else {\n debouncedSearch(q, cfg.debounceMs ?? DEFAULTS.debounceMs);\n }\n },\n setData(data) {\n rawData = [...data];\n offset = 0;\n update();\n },\n setFilter(f) {\n filterFn = f;\n offset = 0;\n update();\n },\n setLimit(n) {\n limit = Math.max(1, n);\n offset = 0;\n update();\n },\n setSort(s) {\n sortFn = s;\n update();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n"],"names":["list","initialData","cfg","listeners","DEFAULTS","rawData","limit","filterFn","sortFn","searchFn","items","q","t","defaultSearch","searchTone","query","offset","view","notify","l","recompute","arr","pages","slice","start","update","timer","debouncedSearch","ms","mutator","nextLimit","nextFilter","nextSort","nextQuery","nextData","nextOffset","clamp","i","total","lim","p","d","f","n","s","page","isEmpty","opts","data","listener"],"mappings":"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"}
@@ -1,74 +1,107 @@
1
- import { debounce as M } from "../function/debounce.js";
2
- import { chunk as x } from "./chunk.js";
3
- import { search as d } from "./search.js";
4
- const D = 10, E = 0.5, F = 1;
5
- function m(a, o, r) {
6
- const s = r ? [...a].sort(r) : [...a];
7
- return x(s, o);
8
- }
9
- function f(a, o, r = "") {
10
- return (r ? d(a, r, E) : a).filter(o);
11
- }
12
- function _(a, o = {}) {
13
- let { limit: r = D, filterFn: s = () => !0, sortFn: h } = o, u = [...a], t = 0, c = "", l = f(u, s), n = m(l, r, h);
14
- const i = () => {
15
- l = f(u, s, c), n = m(l, r, h);
16
- const e = Math.max(0, n.length - 1);
17
- return t = Math.max(0, Math.min(t, e)), n[t] ?? [];
1
+ import { search as A } from "./search.js";
2
+ function U(S, i = {}) {
3
+ const T = /* @__PURE__ */ new Set(), u = { debounceMs: 300, limit: 10, searchTone: 0.5 };
4
+ let x = [...S], a = Math.max(1, i.limit ?? u.limit), m = i.filterFn ?? (() => !0), M = i.sortFn;
5
+ const y = i.searchFn ?? ((t, e, o) => A([...t], e, o)), D = i.searchTone ?? u.searchTone;
6
+ let c = "", n = 0, h = [];
7
+ const d = () => {
8
+ for (const t of T)
9
+ t();
10
+ }, g = () => {
11
+ let t = x;
12
+ c && (t = y(t, c, D)), m && (t = t.filter(m)), t = M ? [...t].sort(M) : [...t];
13
+ const e = Math.max(1, Math.ceil(t.length / a));
14
+ n = Math.min(n, e - 1), h = t;
15
+ }, L = () => {
16
+ if (!h.length) return [];
17
+ const t = n * a;
18
+ return h.slice(t, t + a);
19
+ }, r = () => {
20
+ g(), d();
18
21
  };
19
- return {
20
- get current() {
21
- return n[t] ?? [];
22
- },
23
- set data(e) {
24
- u = [...e], t = 0, i();
22
+ let F;
23
+ const v = (t, e) => {
24
+ F && clearTimeout(F), F = setTimeout(() => {
25
+ c = t, F = void 0, r();
26
+ }, e);
27
+ };
28
+ return g(), {
29
+ batch(t) {
30
+ let e = a, o = m, l = M, f = c, b = x, p = n;
31
+ const w = (s, E, Q) => Math.max(0, Math.min(s, Math.max(0, Math.ceil(E / Q) - 1)));
32
+ t({
33
+ goTo: (s) => {
34
+ p = w(s - 1, h.length, e);
35
+ },
36
+ setData: (s) => {
37
+ b = [...s], p = 0;
38
+ },
39
+ setFilter: (s) => {
40
+ o = s;
41
+ },
42
+ setLimit: (s) => {
43
+ e = Math.max(1, s);
44
+ },
45
+ setQuery: (s) => {
46
+ f = s, p = 0;
47
+ },
48
+ setSort: (s) => {
49
+ l = s;
50
+ }
51
+ }), a = e, m = o, M = l, c = f, x = b, n = p, r();
25
52
  },
26
- filter(e) {
27
- return s = e, t = 0, i();
53
+ get current() {
54
+ return L();
28
55
  },
29
- set limit(e) {
30
- r = Math.max(F, e), i();
56
+ goTo(t) {
57
+ const e = Math.max(1, Math.ceil(h.length / a));
58
+ n = Math.max(0, Math.min(t - 1, e - 1)), d();
31
59
  },
32
60
  get meta() {
61
+ const t = h.length, e = Math.max(1, Math.ceil(t / a)), o = t === 0, l = Math.min(n + 1, e), f = o ? 0 : (l - 1) * a + 1;
33
62
  return {
34
- end: Math.min(r * (t + 1), l.length),
35
- isEmpty: l.length === 0,
36
- isFirst: t === 0,
37
- isLast: t === n.length - 1,
38
- limit: r,
39
- page: t + 1,
40
- pages: Math.ceil(l.length / r),
41
- start: Math.max(0, r * t + 1),
42
- total: l.length
63
+ end: o ? 0 : Math.min(l * a, t),
64
+ isEmpty: o,
65
+ isFirst: l <= 1,
66
+ isLast: l >= e,
67
+ limit: a,
68
+ page: l,
69
+ pages: e,
70
+ start: f,
71
+ total: t
43
72
  };
44
73
  },
45
74
  next() {
46
- t < n.length - 1 && t++;
47
- },
48
- set page(e) {
49
- const g = e - 1, p = g < 0 ? n.length + g : g;
50
- t = Math.max(0, Math.min(p, n.length - 1));
51
- },
52
- get pages() {
53
- return n;
75
+ const t = Math.max(1, Math.ceil(h.length / a));
76
+ n < t - 1 && (n++, d());
54
77
  },
55
78
  prev() {
56
- t > 0 && t--;
79
+ n > 0 && (n--, d());
57
80
  },
58
81
  reset() {
59
- return t = 0, c = "", s = o.filterFn ?? (() => !0), i();
82
+ a = Math.max(1, i.limit ?? u.limit), m = i.filterFn ?? (() => !0), M = i.sortFn, c = "", n = 0, r();
83
+ },
84
+ search(t, e) {
85
+ c = t, n = 0, e?.immediate ? r() : v(t, i.debounceMs ?? u.debounceMs);
86
+ },
87
+ setData(t) {
88
+ x = [...t], n = 0, r();
89
+ },
90
+ setFilter(t) {
91
+ m = t, n = 0, r();
92
+ },
93
+ setLimit(t) {
94
+ a = Math.max(1, t), n = 0, r();
60
95
  },
61
- search: M((e) => (c = e, i())),
62
- sort(e) {
63
- return h = e, i();
96
+ setSort(t) {
97
+ M = t, r();
64
98
  },
65
- *[Symbol.iterator]() {
66
- for (const e of n)
67
- yield e;
99
+ subscribe(t) {
100
+ return T.add(t), () => T.delete(t);
68
101
  }
69
102
  };
70
103
  }
71
104
  export {
72
- _ as list
105
+ U as list
73
106
  };
74
107
  //# sourceMappingURL=list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sources":["../../src/array/list.ts"],"sourcesContent":["import { debounce } from '../function/debounce';\nimport type { Predicate } from '../types';\nimport { chunk } from './chunk';\nimport { search } from './search';\n\ntype Config<T> = {\n filterFn?: Predicate<T>;\n limit?: number;\n sortFn?: (a: T, b: T) => number;\n};\n\nconst DEFAULT_LIMIT = 10;\nconst DEFAULT_SEARCH_TONE = 0.5;\nconst MIN_LIMIT = 1;\n\nfunction getPages<T>(data: T[], size: number, sortFn: Config<T>['sortFn']): T[][] {\n const sortedData = sortFn ? [...data].sort(sortFn) : [...data];\n return chunk<T>(sortedData, size) as T[][];\n}\n\nfunction getData<T>(data: T[], currentFilterFn: Predicate<T>, query = ''): T[] {\n const searchResults = query ? search(data, query, DEFAULT_SEARCH_TONE) : data;\n return searchResults.filter(currentFilterFn) as T[];\n}\n\nexport function list<T>(initialData: T[], config: Config<T> = {}) {\n let { limit = DEFAULT_LIMIT, filterFn = () => true, sortFn } = config;\n let rawData = [...initialData];\n let offset = 0;\n let query = '';\n let data = getData(rawData, filterFn);\n let pages = getPages(data, limit, sortFn);\n\n const update = () => {\n data = getData(rawData, filterFn, query);\n pages = getPages(data, limit, sortFn);\n // Ensure offset is valid for the new page count\n // If pages is empty, offset should be 0. Max index is pages.length - 1\n const maxOffset = Math.max(0, pages.length - 1);\n offset = Math.max(0, Math.min(offset, maxOffset));\n return pages[offset] ?? [];\n };\n\n return {\n get current() {\n return pages[offset] ?? [];\n },\n set data(newData: T[]) {\n rawData = [...newData];\n offset = 0;\n update();\n },\n filter(predicate: (item: T) => boolean) {\n filterFn = predicate;\n offset = 0;\n return update();\n },\n set limit(newLimit: number) {\n limit = Math.max(MIN_LIMIT, newLimit);\n update();\n },\n get meta() {\n return {\n end: Math.min(limit * (offset + 1), data.length),\n isEmpty: data.length === 0,\n isFirst: offset === 0,\n isLast: offset === pages.length - 1,\n limit: limit,\n page: offset + 1,\n pages: Math.ceil(data.length / limit),\n start: Math.max(0, limit * offset + 1),\n total: data.length,\n };\n },\n next() {\n if (offset < pages.length - 1) {\n offset++;\n }\n },\n set page(page: number) {\n const index = page - 1;\n const value = index < 0 ? pages.length + index : index;\n offset = Math.max(0, Math.min(value, pages.length - 1));\n },\n get pages() {\n return pages;\n },\n prev() {\n if (offset > 0) {\n offset--;\n }\n },\n reset() {\n offset = 0;\n query = '';\n filterFn = config.filterFn ?? (() => true);\n return update();\n },\n search: debounce((str: string) => {\n query = str;\n return update();\n }),\n sort(fn?: (a: T, b: T) => number) {\n sortFn = fn;\n return update();\n },\n *[Symbol.iterator]() {\n for (const page of pages) {\n yield page;\n }\n },\n };\n}\n"],"names":["DEFAULT_LIMIT","DEFAULT_SEARCH_TONE","MIN_LIMIT","getPages","data","size","sortFn","sortedData","chunk","getData","currentFilterFn","query","search","list","initialData","config","limit","filterFn","rawData","offset","pages","update","maxOffset","newData","predicate","newLimit","page","index","value","debounce","str","fn"],"mappings":";;;AAWA,MAAMA,IAAgB,IAChBC,IAAsB,KACtBC,IAAY;AAElB,SAASC,EAAYC,GAAWC,GAAcC,GAAoC;AAChF,QAAMC,IAAaD,IAAS,CAAC,GAAGF,CAAI,EAAE,KAAKE,CAAM,IAAI,CAAC,GAAGF,CAAI;AAC7D,SAAOI,EAASD,GAAYF,CAAI;AAClC;AAEA,SAASI,EAAWL,GAAWM,GAA+BC,IAAQ,IAAS;AAE7E,UADsBA,IAAQC,EAAOR,GAAMO,GAAOV,CAAmB,IAAIG,GACpD,OAAOM,CAAe;AAC7C;AAEO,SAASG,EAAQC,GAAkBC,IAAoB,IAAI;AAChE,MAAI,EAAE,OAAAC,IAAQhB,GAAe,UAAAiB,IAAW,MAAM,IAAM,QAAAX,MAAWS,GAC3DG,IAAU,CAAC,GAAGJ,CAAW,GACzBK,IAAS,GACTR,IAAQ,IACRP,IAAOK,EAAQS,GAASD,CAAQ,GAChCG,IAAQjB,EAASC,GAAMY,GAAOV,CAAM;AAExC,QAAMe,IAAS,MAAM;AACnB,IAAAjB,IAAOK,EAAQS,GAASD,GAAUN,CAAK,GACvCS,IAAQjB,EAASC,GAAMY,GAAOV,CAAM;AAGpC,UAAMgB,IAAY,KAAK,IAAI,GAAGF,EAAM,SAAS,CAAC;AAC9C,WAAAD,IAAS,KAAK,IAAI,GAAG,KAAK,IAAIA,GAAQG,CAAS,CAAC,GACzCF,EAAMD,CAAM,KAAK,CAAA;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,IAAI,UAAU;AACZ,aAAOC,EAAMD,CAAM,KAAK,CAAA;AAAA,IAC1B;AAAA,IACA,IAAI,KAAKI,GAAc;AACrB,MAAAL,IAAU,CAAC,GAAGK,CAAO,GACrBJ,IAAS,GACTE,EAAA;AAAA,IACF;AAAA,IACA,OAAOG,GAAiC;AACtC,aAAAP,IAAWO,GACXL,IAAS,GACFE,EAAA;AAAA,IACT;AAAA,IACA,IAAI,MAAMI,GAAkB;AAC1B,MAAAT,IAAQ,KAAK,IAAId,GAAWuB,CAAQ,GACpCJ,EAAA;AAAA,IACF;AAAA,IACA,IAAI,OAAO;AACT,aAAO;AAAA,QACL,KAAK,KAAK,IAAIL,KAASG,IAAS,IAAIf,EAAK,MAAM;AAAA,QAC/C,SAASA,EAAK,WAAW;AAAA,QACzB,SAASe,MAAW;AAAA,QACpB,QAAQA,MAAWC,EAAM,SAAS;AAAA,QAClC,OAAAJ;AAAA,QACA,MAAMG,IAAS;AAAA,QACf,OAAO,KAAK,KAAKf,EAAK,SAASY,CAAK;AAAA,QACpC,OAAO,KAAK,IAAI,GAAGA,IAAQG,IAAS,CAAC;AAAA,QACrC,OAAOf,EAAK;AAAA,MAAA;AAAA,IAEhB;AAAA,IACA,OAAO;AACL,MAAIe,IAASC,EAAM,SAAS,KAC1BD;AAAA,IAEJ;AAAA,IACA,IAAI,KAAKO,GAAc;AACrB,YAAMC,IAAQD,IAAO,GACfE,IAAQD,IAAQ,IAAIP,EAAM,SAASO,IAAQA;AACjD,MAAAR,IAAS,KAAK,IAAI,GAAG,KAAK,IAAIS,GAAOR,EAAM,SAAS,CAAC,CAAC;AAAA,IACxD;AAAA,IACA,IAAI,QAAQ;AACV,aAAOA;AAAA,IACT;AAAA,IACA,OAAO;AACL,MAAID,IAAS,KACXA;AAAA,IAEJ;AAAA,IACA,QAAQ;AACN,aAAAA,IAAS,GACTR,IAAQ,IACRM,IAAWF,EAAO,aAAa,MAAM,KAC9BM,EAAA;AAAA,IACT;AAAA,IACA,QAAQQ,EAAS,CAACC,OAChBnB,IAAQmB,GACDT,EAAA,EACR;AAAA,IACD,KAAKU,GAA6B;AAChC,aAAAzB,IAASyB,GACFV,EAAA;AAAA,IACT;AAAA,IACA,EAAE,OAAO,QAAQ,IAAI;AACnB,iBAAWK,KAAQN;AACjB,cAAMM;AAAA,IAEV;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"list.js","sources":["../../src/array/list.ts"],"sourcesContent":["import type { Predicate, Sorter } from '../types';\nimport { search as defaultSearch } from './search';\n\n// #region Meta\nexport type Meta = Readonly<{\n end: number; // inclusive\n isEmpty: boolean;\n isFirst: boolean;\n isLast: boolean;\n limit: number;\n page: number; // 1-based\n pages: number;\n start: number; // 1-based\n total: number;\n}>;\n// #endregion Meta\n\n// #region List\nexport type List<T, F, S> = {\n readonly current: readonly T[];\n readonly meta: Meta;\n subscribe(listener: () => void): () => void;\n\n goTo(page: number): void;\n next(): void;\n prev(): void;\n reset(): void;\n search(query: string, opts?: { immediate?: boolean }): void;\n setData?(data: readonly T[]): void; // implemented by local\n setFilter(filter: F): void;\n setLimit(n: number): void;\n setSort(sort?: S): void;\n\n // Batch updates across properties in one recompute/refetch\n batch(\n mutator: (ctx: {\n setLimit(n: number): void;\n setFilter(f: F): void;\n setSort(s?: S): void;\n setQuery(q: string): void;\n setData?(d: readonly T[]): void; // local-only\n goTo(p: number): void; // 1-based\n }) => void,\n ): void;\n};\n// #endregion List\n\n// #region LocalConfig\ntype LocalConfig<T> = Readonly<{\n debounceMs?: number;\n filterFn?: Predicate<T>;\n limit?: number;\n searchFn?: (items: readonly T[], query: string, tone: number) => readonly T[];\n searchTone?: number;\n sortFn?: Sorter<T>;\n}>;\n// #endregion LocalConfig\n\nexport function list<T>(initialData: readonly T[], cfg: LocalConfig<T> = {}): List<T, Predicate<T>, Sorter<T>> {\n const listeners = new Set<() => void>();\n\n const DEFAULTS = { debounceMs: 300, limit: 10, searchTone: 0.5 } as const;\n\n let rawData: readonly T[] = [...initialData];\n let limit = Math.max(1, cfg.limit ?? DEFAULTS.limit);\n let filterFn: Predicate<T> = cfg.filterFn ?? (() => true);\n let sortFn: Sorter<T> | undefined = cfg.sortFn;\n const searchFn = cfg.searchFn ?? ((items: readonly T[], q: string, t: number) => defaultSearch([...items], q, t));\n const searchTone = cfg.searchTone ?? DEFAULTS.searchTone;\n\n let query = '';\n let offset = 0;\n let view: readonly T[] = [];\n\n const notify = () => {\n for (const l of listeners) {\n l();\n }\n };\n\n const recompute = () => {\n let arr = rawData;\n\n if (query) arr = searchFn(arr, query, searchTone);\n if (filterFn) arr = arr.filter(filterFn);\n arr = sortFn ? [...arr].sort(sortFn) : [...arr];\n\n const pages = Math.max(1, Math.ceil(arr.length / limit));\n offset = Math.min(offset, pages - 1);\n view = arr;\n };\n\n const slice = (): readonly T[] => {\n if (!view.length) return [];\n const start = offset * limit;\n return view.slice(start, start + limit);\n };\n\n const update = () => {\n recompute();\n notify();\n };\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const debouncedSearch = (q: string, ms: number) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n query = q;\n timer = undefined;\n void update();\n }, ms);\n };\n\n // initial compute\n recompute();\n\n return {\n batch(mutator) {\n let nextLimit = limit;\n let nextFilter = filterFn;\n let nextSort = sortFn;\n let nextQuery = query;\n let nextData = rawData;\n let nextOffset = offset;\n\n const clamp = (i: number, total: number, lim: number) =>\n Math.max(0, Math.min(i, Math.max(0, Math.ceil(total / lim) - 1)));\n\n mutator({\n goTo: (p) => {\n nextOffset = clamp(p - 1, view.length, nextLimit);\n },\n setData: (d) => {\n nextData = [...d];\n nextOffset = 0;\n },\n setFilter: (f) => {\n nextFilter = f;\n },\n setLimit: (n) => {\n nextLimit = Math.max(1, n);\n },\n setQuery: (q) => {\n nextQuery = q;\n nextOffset = 0;\n },\n setSort: (s) => {\n nextSort = s;\n },\n });\n\n // apply once\n limit = nextLimit;\n filterFn = nextFilter;\n sortFn = nextSort;\n query = nextQuery;\n rawData = nextData;\n offset = nextOffset;\n\n update();\n },\n get current() {\n return slice();\n },\n goTo(page) {\n const pages = Math.max(1, Math.ceil(view.length / limit));\n offset = Math.max(0, Math.min(page - 1, pages - 1));\n notify();\n },\n get meta() {\n const total = view.length;\n const pages = Math.max(1, Math.ceil(total / limit));\n const isEmpty = total === 0;\n const page = Math.min(offset + 1, pages);\n const start = isEmpty ? 0 : (page - 1) * limit + 1;\n const end = isEmpty ? 0 : Math.min(page * limit, total);\n return {\n end,\n isEmpty,\n isFirst: page <= 1,\n isLast: page >= pages,\n limit,\n page,\n pages,\n start,\n total,\n };\n },\n next() {\n const pages = Math.max(1, Math.ceil(view.length / limit));\n if (offset < pages - 1) {\n offset++;\n notify();\n }\n },\n prev() {\n if (offset > 0) {\n offset--;\n notify();\n }\n },\n reset() {\n limit = Math.max(1, cfg.limit ?? DEFAULTS.limit);\n filterFn = cfg.filterFn ?? (() => true);\n sortFn = cfg.sortFn;\n query = '';\n offset = 0;\n update();\n },\n search(q, opts) {\n query = q;\n offset = 0;\n if (opts?.immediate) {\n update();\n } else {\n debouncedSearch(q, cfg.debounceMs ?? DEFAULTS.debounceMs);\n }\n },\n setData(data) {\n rawData = [...data];\n offset = 0;\n update();\n },\n setFilter(f) {\n filterFn = f;\n offset = 0;\n update();\n },\n setLimit(n) {\n limit = Math.max(1, n);\n offset = 0;\n update();\n },\n setSort(s) {\n sortFn = s;\n update();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n"],"names":["list","initialData","cfg","listeners","DEFAULTS","rawData","limit","filterFn","sortFn","searchFn","items","q","t","defaultSearch","searchTone","query","offset","view","notify","l","recompute","arr","pages","slice","start","update","timer","debouncedSearch","ms","mutator","nextLimit","nextFilter","nextSort","nextQuery","nextData","nextOffset","clamp","i","total","lim","p","d","f","n","page","isEmpty","opts","data","s","listener"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function Q(r){const y=new Set,b=Math.max(1,r.limit??10),O=r.debounceMs??300;let a=1,n=b,h="",u=r.initialFilter,d=r.initialSort,M=[],c=0,f=!1,x=null;const m=new Map,w=new Map,v=t=>JSON.stringify(t),F=()=>({filter:u,limit:n,page:a,search:h||void 0,sort:d}),p=t=>{M=t.items,c=t.total??0;const e=Math.max(1,Math.ceil(c/n));a=Math.min(Math.max(1,a),e)},L=()=>{for(const t of y)t()},P=async t=>{const e=v(t);if(m.has(e)){p(m.get(e));return}if(w.has(e)){await w.get(e),p(m.get(e));return}f=!0,x=null,L();const s=r.fetch(t).then(l=>{m.set(e,l),p(l)}).catch(l=>{x=l?.message??"Request failed",M=[],c=0}).finally(()=>{w.delete(e),f=!1,L()});w.set(e,s),await s},i=async()=>{await P(F())};let g;const k=()=>{g&&clearTimeout(g),g=setTimeout(()=>{g=void 0,i()},O)};return{async batch(t){let e=a,s=n,l=h,S=u,T=d;t({goTo:o=>{e=Math.max(1,o|0)},setFilter:o=>{S=o,e=1},setLimit:o=>{s=Math.max(1,o),e=1},setQuery:o=>{l=o,e=1},setSort:o=>{T=o,e=1}}),a=e,n=s,h=l,u=S,d=T,await i()},get current(){return M},async goTo(t){a=Math.max(1,t|0),await i()},invalidate(){m.clear()},get meta(){const t=c===0,e=Math.max(1,Math.ceil(c/n)),s=Math.min(a,e),l=t?0:(s-1)*n+1;return{end:t?0:Math.min(s*n,c),error:x,isEmpty:t,isFirst:s<=1,isLast:s>=e,limit:n,loading:f,page:s,pages:e,start:l,total:c}},async next(){a+=1,await i()},async prev(){a=Math.max(1,a-1),await i()},async refresh(){m.delete(v(F())),await i()},async reset(){a=1,n=b,h="",u=r.initialFilter,d=r.initialSort,m.clear(),await i()},async search(t,e){h=t,a=1,e?.immediate?await i():k()},async setFilter(t){u=t,a=1,await i()},async setLimit(t){n=Math.max(1,t),a=1,await i()},async setSort(t){d=t,a=1,await i()},subscribe(t){return y.add(t),y.size===1&&M.length===0&&!f&&i(),()=>y.delete(t)}}}exports.remoteList=Q;
2
+ //# sourceMappingURL=remoteList.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteList.cjs","sources":["../../src/array/remoteList.ts"],"sourcesContent":["// #region RemoteMeta\nexport type RemoteMeta = Readonly<{\n end: number; // inclusive\n error: string | null;\n isEmpty: boolean;\n isFirst: boolean;\n isLast: boolean;\n limit: number;\n loading: boolean;\n page: number; // 1-based\n pages: number;\n start: number; // 1-based\n total: number;\n}>;\n// #endregion RemoteMeta\n\n// #region RemoteList\nexport type RemoteList<T, F, S> = {\n readonly current: readonly T[];\n readonly meta: RemoteMeta;\n subscribe(listener: () => void): () => void;\n\n goTo(page: number): Promise<void>;\n invalidate?(): void;\n next(): Promise<void>;\n prev(): Promise<void>;\n refresh(): Promise<void>;\n reset(): Promise<void>;\n search(query: string, opts?: { immediate?: boolean }): Promise<void>;\n setFilter(filter: F): Promise<void>;\n setLimit(n: number): Promise<void>;\n setSort(sort?: S): Promise<void>;\n\n // Batch updates across properties in one recompute/refetch\n batch(\n mutator: (ctx: {\n setLimit(n: number): void;\n setFilter(f: F): void;\n setSort(s?: S): void;\n setQuery(q: string): void;\n setData?(d: readonly T[]): void; // local-only\n goTo(p: number): void; // 1-based\n }) => void,\n ): Promise<void>;\n};\n// #endregion RemoteList\n\n// #region RemoteConfig\ntype RemoteQuery<F, S> = Readonly<{\n filter?: F;\n limit: number;\n page: number; // 1-based\n search?: string;\n sort?: S;\n}>;\n\ntype RemoteResult<T> = Readonly<{ items: readonly T[]; total: number }>;\n\ntype RemoteConfig<T, F, S> = Readonly<{\n debounceMs?: number;\n fetch: (q: RemoteQuery<F, S>) => Promise<RemoteResult<T>>;\n initialFilter?: F;\n initialSort?: S;\n limit?: number;\n}>;\n// #endregion RemoteConfig\n\nexport function remoteList<T, F = Record<string, unknown>, S = { key?: string; dir?: 'asc' | 'desc' }>(\n cfg: RemoteConfig<T, F, S>,\n): RemoteList<T, F, S> {\n const listeners = new Set<() => void>();\n\n const limitDefault = Math.max(1, cfg.limit ?? 10);\n const debounceMs = cfg.debounceMs ?? 300;\n\n let page = 1;\n let limit = limitDefault;\n let search = '';\n let filter = cfg.initialFilter as F | undefined;\n let sort = cfg.initialSort as S | undefined;\n\n let items: readonly T[] = [];\n let total = 0;\n let loading = false;\n let error: string | null = null;\n\n const cache = new Map<string, RemoteResult<T>>();\n const inflight = new Map<string, Promise<void>>();\n\n const keyOf = (q: RemoteQuery<F, S>) => JSON.stringify(q);\n const queryOf = (): RemoteQuery<F, S> => ({\n filter,\n limit,\n page,\n search: search || undefined,\n sort,\n });\n\n const assign = (res: RemoteResult<T>) => {\n items = res.items;\n total = res.total ?? 0;\n const pages = Math.max(1, Math.ceil(total / limit));\n page = Math.min(Math.max(1, page), pages);\n };\n\n const notify = () => {\n for (const l of listeners) {\n l();\n }\n };\n\n const fetchQuery = async (q: RemoteQuery<F, S>) => {\n const k = keyOf(q);\n if (cache.has(k)) {\n assign(cache.get(k)!);\n return;\n }\n if (inflight.has(k)) {\n await inflight.get(k);\n assign(cache.get(k)!);\n return;\n }\n loading = true;\n error = null;\n notify();\n const p = cfg\n .fetch(q)\n .then((res) => {\n cache.set(k, res);\n assign(res);\n })\n .catch((e) => {\n error = e?.message ?? 'Request failed';\n items = [];\n total = 0;\n })\n .finally(() => {\n inflight.delete(k);\n loading = false;\n notify();\n });\n inflight.set(k, p);\n await p;\n };\n\n const update = async () => {\n await fetchQuery(queryOf());\n };\n\n // debounced search\n let timer: ReturnType<typeof setTimeout> | undefined;\n const debounced = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = undefined;\n void update();\n }, debounceMs);\n };\n\n // initial fetch is on the first subscriber or call to refresh; up to you\n return {\n async batch(mutator) {\n // Stage local copies\n let nextPage = page;\n let nextLimit = limit;\n let nextSearch = search;\n let nextFilter = filter as F | undefined;\n let nextSort = sort as S | undefined;\n\n mutator({\n goTo: (p: number) => {\n nextPage = Math.max(1, p | 0);\n },\n setFilter: (f: F) => {\n nextFilter = f;\n nextPage = 1;\n },\n setLimit: (n) => {\n nextLimit = Math.max(1, n);\n nextPage = 1;\n },\n setQuery: (q: string) => {\n nextSearch = q;\n nextPage = 1;\n },\n setSort: (s?: S) => {\n nextSort = s;\n nextPage = 1;\n },\n });\n\n // Apply and update at once\n page = nextPage;\n limit = nextLimit;\n search = nextSearch;\n filter = nextFilter;\n sort = nextSort;\n\n await update();\n },\n get current() {\n return items;\n },\n async goTo(p) {\n page = Math.max(1, p | 0);\n await update();\n },\n invalidate() {\n cache.clear();\n },\n get meta() {\n const isEmpty = total === 0;\n const pages = Math.max(1, Math.ceil(total / limit));\n const safePage = Math.min(page, pages);\n const start = isEmpty ? 0 : (safePage - 1) * limit + 1;\n const end = isEmpty ? 0 : Math.min(safePage * limit, total);\n return {\n end,\n error,\n isEmpty,\n isFirst: safePage <= 1,\n isLast: safePage >= pages,\n limit,\n loading,\n page: safePage,\n pages,\n start,\n total,\n };\n },\n async next() {\n page += 1;\n await update();\n },\n async prev() {\n page = Math.max(1, page - 1);\n await update();\n },\n async refresh() {\n cache.delete(keyOf(queryOf()));\n await update();\n },\n async reset() {\n page = 1;\n limit = limitDefault;\n search = '';\n filter = cfg.initialFilter as F | undefined;\n sort = cfg.initialSort as S | undefined;\n cache.clear();\n await update();\n },\n async search(q, opts) {\n search = q;\n page = 1;\n if (opts?.immediate) await update();\n else debounced();\n },\n async setFilter(f) {\n filter = f;\n page = 1;\n await update();\n },\n async setLimit(n) {\n limit = Math.max(1, n);\n page = 1;\n await update();\n },\n async setSort(s) {\n sort = s;\n page = 1;\n await update();\n },\n subscribe(listener) {\n listeners.add(listener);\n // optional: trigger an initial load on the first subscription\n if (listeners.size === 1 && items.length === 0 && !loading) {\n void update();\n }\n return () => listeners.delete(listener);\n },\n };\n}\n"],"names":["remoteList","cfg","listeners","limitDefault","debounceMs","page","limit","search","filter","sort","items","total","loading","error","cache","inflight","keyOf","q","queryOf","assign","res","pages","notify","l","fetchQuery","k","p","e","update","timer","debounced","mutator","nextPage","nextLimit","nextSearch","nextFilter","nextSort","f","n","s","isEmpty","safePage","start","opts","listener"],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ function Q(r) {
2
+ const y = /* @__PURE__ */ new Set(), b = Math.max(1, r.limit ?? 10), O = r.debounceMs ?? 300;
3
+ let a = 1, n = b, m = "", u = r.initialFilter, d = r.initialSort, M = [], c = 0, f = !1, g = null;
4
+ const h = /* @__PURE__ */ new Map(), w = /* @__PURE__ */ new Map(), v = (t) => JSON.stringify(t), F = () => ({
5
+ filter: u,
6
+ limit: n,
7
+ page: a,
8
+ search: m || void 0,
9
+ sort: d
10
+ }), p = (t) => {
11
+ M = t.items, c = t.total ?? 0;
12
+ const e = Math.max(1, Math.ceil(c / n));
13
+ a = Math.min(Math.max(1, a), e);
14
+ }, L = () => {
15
+ for (const t of y)
16
+ t();
17
+ }, k = async (t) => {
18
+ const e = v(t);
19
+ if (h.has(e)) {
20
+ p(h.get(e));
21
+ return;
22
+ }
23
+ if (w.has(e)) {
24
+ await w.get(e), p(h.get(e));
25
+ return;
26
+ }
27
+ f = !0, g = null, L();
28
+ const s = r.fetch(t).then((l) => {
29
+ h.set(e, l), p(l);
30
+ }).catch((l) => {
31
+ g = l?.message ?? "Request failed", M = [], c = 0;
32
+ }).finally(() => {
33
+ w.delete(e), f = !1, L();
34
+ });
35
+ w.set(e, s), await s;
36
+ }, i = async () => {
37
+ await k(F());
38
+ };
39
+ let x;
40
+ const P = () => {
41
+ x && clearTimeout(x), x = setTimeout(() => {
42
+ x = void 0, i();
43
+ }, O);
44
+ };
45
+ return {
46
+ async batch(t) {
47
+ let e = a, s = n, l = m, S = u, T = d;
48
+ t({
49
+ goTo: (o) => {
50
+ e = Math.max(1, o | 0);
51
+ },
52
+ setFilter: (o) => {
53
+ S = o, e = 1;
54
+ },
55
+ setLimit: (o) => {
56
+ s = Math.max(1, o), e = 1;
57
+ },
58
+ setQuery: (o) => {
59
+ l = o, e = 1;
60
+ },
61
+ setSort: (o) => {
62
+ T = o, e = 1;
63
+ }
64
+ }), a = e, n = s, m = l, u = S, d = T, await i();
65
+ },
66
+ get current() {
67
+ return M;
68
+ },
69
+ async goTo(t) {
70
+ a = Math.max(1, t | 0), await i();
71
+ },
72
+ invalidate() {
73
+ h.clear();
74
+ },
75
+ get meta() {
76
+ const t = c === 0, e = Math.max(1, Math.ceil(c / n)), s = Math.min(a, e), l = t ? 0 : (s - 1) * n + 1;
77
+ return {
78
+ end: t ? 0 : Math.min(s * n, c),
79
+ error: g,
80
+ isEmpty: t,
81
+ isFirst: s <= 1,
82
+ isLast: s >= e,
83
+ limit: n,
84
+ loading: f,
85
+ page: s,
86
+ pages: e,
87
+ start: l,
88
+ total: c
89
+ };
90
+ },
91
+ async next() {
92
+ a += 1, await i();
93
+ },
94
+ async prev() {
95
+ a = Math.max(1, a - 1), await i();
96
+ },
97
+ async refresh() {
98
+ h.delete(v(F())), await i();
99
+ },
100
+ async reset() {
101
+ a = 1, n = b, m = "", u = r.initialFilter, d = r.initialSort, h.clear(), await i();
102
+ },
103
+ async search(t, e) {
104
+ m = t, a = 1, e?.immediate ? await i() : P();
105
+ },
106
+ async setFilter(t) {
107
+ u = t, a = 1, await i();
108
+ },
109
+ async setLimit(t) {
110
+ n = Math.max(1, t), a = 1, await i();
111
+ },
112
+ async setSort(t) {
113
+ d = t, a = 1, await i();
114
+ },
115
+ subscribe(t) {
116
+ return y.add(t), y.size === 1 && M.length === 0 && !f && i(), () => y.delete(t);
117
+ }
118
+ };
119
+ }
120
+ export {
121
+ Q as remoteList
122
+ };
123
+ //# sourceMappingURL=remoteList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteList.js","sources":["../../src/array/remoteList.ts"],"sourcesContent":["// #region RemoteMeta\nexport type RemoteMeta = Readonly<{\n end: number; // inclusive\n error: string | null;\n isEmpty: boolean;\n isFirst: boolean;\n isLast: boolean;\n limit: number;\n loading: boolean;\n page: number; // 1-based\n pages: number;\n start: number; // 1-based\n total: number;\n}>;\n// #endregion RemoteMeta\n\n// #region RemoteList\nexport type RemoteList<T, F, S> = {\n readonly current: readonly T[];\n readonly meta: RemoteMeta;\n subscribe(listener: () => void): () => void;\n\n goTo(page: number): Promise<void>;\n invalidate?(): void;\n next(): Promise<void>;\n prev(): Promise<void>;\n refresh(): Promise<void>;\n reset(): Promise<void>;\n search(query: string, opts?: { immediate?: boolean }): Promise<void>;\n setFilter(filter: F): Promise<void>;\n setLimit(n: number): Promise<void>;\n setSort(sort?: S): Promise<void>;\n\n // Batch updates across properties in one recompute/refetch\n batch(\n mutator: (ctx: {\n setLimit(n: number): void;\n setFilter(f: F): void;\n setSort(s?: S): void;\n setQuery(q: string): void;\n setData?(d: readonly T[]): void; // local-only\n goTo(p: number): void; // 1-based\n }) => void,\n ): Promise<void>;\n};\n// #endregion RemoteList\n\n// #region RemoteConfig\ntype RemoteQuery<F, S> = Readonly<{\n filter?: F;\n limit: number;\n page: number; // 1-based\n search?: string;\n sort?: S;\n}>;\n\ntype RemoteResult<T> = Readonly<{ items: readonly T[]; total: number }>;\n\ntype RemoteConfig<T, F, S> = Readonly<{\n debounceMs?: number;\n fetch: (q: RemoteQuery<F, S>) => Promise<RemoteResult<T>>;\n initialFilter?: F;\n initialSort?: S;\n limit?: number;\n}>;\n// #endregion RemoteConfig\n\nexport function remoteList<T, F = Record<string, unknown>, S = { key?: string; dir?: 'asc' | 'desc' }>(\n cfg: RemoteConfig<T, F, S>,\n): RemoteList<T, F, S> {\n const listeners = new Set<() => void>();\n\n const limitDefault = Math.max(1, cfg.limit ?? 10);\n const debounceMs = cfg.debounceMs ?? 300;\n\n let page = 1;\n let limit = limitDefault;\n let search = '';\n let filter = cfg.initialFilter as F | undefined;\n let sort = cfg.initialSort as S | undefined;\n\n let items: readonly T[] = [];\n let total = 0;\n let loading = false;\n let error: string | null = null;\n\n const cache = new Map<string, RemoteResult<T>>();\n const inflight = new Map<string, Promise<void>>();\n\n const keyOf = (q: RemoteQuery<F, S>) => JSON.stringify(q);\n const queryOf = (): RemoteQuery<F, S> => ({\n filter,\n limit,\n page,\n search: search || undefined,\n sort,\n });\n\n const assign = (res: RemoteResult<T>) => {\n items = res.items;\n total = res.total ?? 0;\n const pages = Math.max(1, Math.ceil(total / limit));\n page = Math.min(Math.max(1, page), pages);\n };\n\n const notify = () => {\n for (const l of listeners) {\n l();\n }\n };\n\n const fetchQuery = async (q: RemoteQuery<F, S>) => {\n const k = keyOf(q);\n if (cache.has(k)) {\n assign(cache.get(k)!);\n return;\n }\n if (inflight.has(k)) {\n await inflight.get(k);\n assign(cache.get(k)!);\n return;\n }\n loading = true;\n error = null;\n notify();\n const p = cfg\n .fetch(q)\n .then((res) => {\n cache.set(k, res);\n assign(res);\n })\n .catch((e) => {\n error = e?.message ?? 'Request failed';\n items = [];\n total = 0;\n })\n .finally(() => {\n inflight.delete(k);\n loading = false;\n notify();\n });\n inflight.set(k, p);\n await p;\n };\n\n const update = async () => {\n await fetchQuery(queryOf());\n };\n\n // debounced search\n let timer: ReturnType<typeof setTimeout> | undefined;\n const debounced = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = undefined;\n void update();\n }, debounceMs);\n };\n\n // initial fetch is on the first subscriber or call to refresh; up to you\n return {\n async batch(mutator) {\n // Stage local copies\n let nextPage = page;\n let nextLimit = limit;\n let nextSearch = search;\n let nextFilter = filter as F | undefined;\n let nextSort = sort as S | undefined;\n\n mutator({\n goTo: (p: number) => {\n nextPage = Math.max(1, p | 0);\n },\n setFilter: (f: F) => {\n nextFilter = f;\n nextPage = 1;\n },\n setLimit: (n) => {\n nextLimit = Math.max(1, n);\n nextPage = 1;\n },\n setQuery: (q: string) => {\n nextSearch = q;\n nextPage = 1;\n },\n setSort: (s?: S) => {\n nextSort = s;\n nextPage = 1;\n },\n });\n\n // Apply and update at once\n page = nextPage;\n limit = nextLimit;\n search = nextSearch;\n filter = nextFilter;\n sort = nextSort;\n\n await update();\n },\n get current() {\n return items;\n },\n async goTo(p) {\n page = Math.max(1, p | 0);\n await update();\n },\n invalidate() {\n cache.clear();\n },\n get meta() {\n const isEmpty = total === 0;\n const pages = Math.max(1, Math.ceil(total / limit));\n const safePage = Math.min(page, pages);\n const start = isEmpty ? 0 : (safePage - 1) * limit + 1;\n const end = isEmpty ? 0 : Math.min(safePage * limit, total);\n return {\n end,\n error,\n isEmpty,\n isFirst: safePage <= 1,\n isLast: safePage >= pages,\n limit,\n loading,\n page: safePage,\n pages,\n start,\n total,\n };\n },\n async next() {\n page += 1;\n await update();\n },\n async prev() {\n page = Math.max(1, page - 1);\n await update();\n },\n async refresh() {\n cache.delete(keyOf(queryOf()));\n await update();\n },\n async reset() {\n page = 1;\n limit = limitDefault;\n search = '';\n filter = cfg.initialFilter as F | undefined;\n sort = cfg.initialSort as S | undefined;\n cache.clear();\n await update();\n },\n async search(q, opts) {\n search = q;\n page = 1;\n if (opts?.immediate) await update();\n else debounced();\n },\n async setFilter(f) {\n filter = f;\n page = 1;\n await update();\n },\n async setLimit(n) {\n limit = Math.max(1, n);\n page = 1;\n await update();\n },\n async setSort(s) {\n sort = s;\n page = 1;\n await update();\n },\n subscribe(listener) {\n listeners.add(listener);\n // optional: trigger an initial load on the first subscription\n if (listeners.size === 1 && items.length === 0 && !loading) {\n void update();\n }\n return () => listeners.delete(listener);\n },\n };\n}\n"],"names":["remoteList","cfg","listeners","limitDefault","debounceMs","page","limit","search","filter","sort","items","total","loading","error","cache","inflight","keyOf","q","queryOf","assign","res","pages","notify","l","fetchQuery","k","p","e","update","timer","debounced","mutator","nextPage","nextLimit","nextSearch","nextFilter","nextSort","f","n","s","isEmpty","safePage","start","opts","listener"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt.cjs","sources":["../../src/async/attempt.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\nimport type { Fn } from '../types';\nimport { predict } from './predict';\nimport { retry } from './retry';\n\ntype AttemptOptions = {\n identifier?: string;\n retries?: number;\n silent?: boolean;\n timeout?: number;\n};\n\n/**\n * Attempts to execute a function with advanced error handling and retry logic.\n *\n * @example\n * ```ts\n * const unreliableFunction = async () => {\n * if (Math.random() < 0.7) throw new Error ('Random failure');\n * return 'Success!';\n * };\n *\n * await attempt(\n * unreliableFunction,\n * { retries: 3, silent: false, timeout: 5000 }); // Success! (or undefined if all attempts failed)\n * ```\n *\n * @param fn - The function to be executed.\n * @param [options] - Configuration options for the attempt.\n * @param [options.identifier] - Custom identifier for logging purposes.\n * @param [options.retries=0] - Number of retry attempts if the function fails.\n * @param [options.silent=false] - If true, suppresses error logging.\n * @param [options.timeout=7000] - Timeout in milliseconds for function execution.\n *\n * @returns The result of the function or undefined if it failed.\n */\nexport async function attempt<T extends Fn, R = Awaited<ReturnType<T>>>(\n fn: T,\n { silent = false, retries = 0, timeout = 7000, identifier = fn.name || 'anonymous function' }: AttemptOptions = {},\n): Promise<R | undefined> {\n try {\n return await retry(() => predict<R>(() => fn(), { timeout }), { times: retries + 1 });\n } catch (err) {\n if (!silent) {\n Logit.error(`attempt(${identifier}) -> all attempts failed`, { cause: err });\n }\n return undefined;\n }\n}\n"],"names":["attempt","fn","silent","retries","timeout","identifier","retry","predict","err","Logit"],"mappings":"+KAoCA,eAAsBA,EACpBC,EACA,CAAE,OAAAC,EAAS,GAAO,QAAAC,EAAU,EAAG,QAAAC,EAAU,IAAM,WAAAC,EAAaJ,EAAG,MAAQ,oBAAA,EAAyC,CAAA,EACxF,CACxB,GAAI,CACF,OAAO,MAAMK,EAAAA,MAAM,IAAMC,EAAAA,QAAW,IAAMN,EAAA,EAAM,CAAE,QAAAG,CAAA,CAAS,EAAG,CAAE,MAAOD,EAAU,EAAG,CACtF,OAASK,EAAK,CACPN,GACHO,QAAM,MAAM,WAAWJ,CAAU,2BAA4B,CAAE,MAAOG,EAAK,EAE7E,MACF,CACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt.js","sources":["../../src/async/attempt.ts"],"sourcesContent":["import { Logit } from '@vielzeug/logit';\nimport type { Fn } from '../types';\nimport { predict } from './predict';\nimport { retry } from './retry';\n\ntype AttemptOptions = {\n identifier?: string;\n retries?: number;\n silent?: boolean;\n timeout?: number;\n};\n\n/**\n * Attempts to execute a function with advanced error handling and retry logic.\n *\n * @example\n * ```ts\n * const unreliableFunction = async () => {\n * if (Math.random() < 0.7) throw new Error ('Random failure');\n * return 'Success!';\n * };\n *\n * await attempt(\n * unreliableFunction,\n * { retries: 3, silent: false, timeout: 5000 }); // Success! (or undefined if all attempts failed)\n * ```\n *\n * @param fn - The function to be executed.\n * @param [options] - Configuration options for the attempt.\n * @param [options.identifier] - Custom identifier for logging purposes.\n * @param [options.retries=0] - Number of retry attempts if the function fails.\n * @param [options.silent=false] - If true, suppresses error logging.\n * @param [options.timeout=7000] - Timeout in milliseconds for function execution.\n *\n * @returns The result of the function or undefined if it failed.\n */\nexport async function attempt<T extends Fn, R = Awaited<ReturnType<T>>>(\n fn: T,\n { silent = false, retries = 0, timeout = 7000, identifier = fn.name || 'anonymous function' }: AttemptOptions = {},\n): Promise<R | undefined> {\n try {\n return await retry(() => predict<R>(() => fn(), { timeout }), { times: retries + 1 });\n } catch (err) {\n if (!silent) {\n Logit.error(`attempt(${identifier}) -> all attempts failed`, { cause: err });\n }\n return undefined;\n }\n}\n"],"names":["attempt","fn","silent","retries","timeout","identifier","retry","predict","err","Logit"],"mappings":";;;AAoCA,eAAsBA,EACpBC,GACA,EAAE,QAAAC,IAAS,IAAO,SAAAC,IAAU,GAAG,SAAAC,IAAU,KAAM,YAAAC,IAAaJ,EAAG,QAAQ,qBAAA,IAAyC,CAAA,GACxF;AACxB,MAAI;AACF,WAAO,MAAMK,EAAM,MAAMC,EAAW,MAAMN,EAAA,GAAM,EAAE,SAAAG,EAAA,CAAS,GAAG,EAAE,OAAOD,IAAU,GAAG;AAAA,EACtF,SAASK,GAAK;AACZ,IAAKN,KACHO,EAAM,MAAM,WAAWJ,CAAU,4BAA4B,EAAE,OAAOG,GAAK;AAE7E;AAAA,EACF;AACF;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function i(){let e,r;return{promise:new Promise((t,o)=>{e=t,r=o}),reject:r,resolve:e}}exports.defer=i;
2
+ //# sourceMappingURL=defer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defer.cjs","sources":["../../src/async/defer.ts"],"sourcesContent":["/**\n * Creates a deferred promise with resolve and reject methods exposed.\n * Useful for creating promises that are resolved/rejected externally.\n *\n * @example\n * ```ts\n * const deferred = defer<string>();\n *\n * setTimeout(() => {\n * deferred.resolve('Done!');\n * }, 1000);\n *\n * const result = await deferred.promise; // 'Done!'\n * ```\n *\n * @returns Object with promise and resolve/reject methods\n */\nexport function defer<T = void>(): {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n} {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, reject, resolve };\n}\n"],"names":["defer","resolve","reject","res","rej"],"mappings":"gFAiBO,SAASA,GAId,CACA,IAAIC,EACAC,EAOJ,MAAO,CAAE,QALO,IAAI,QAAW,CAACC,EAAKC,IAAQ,CAC3CH,EAAUE,EACVD,EAASE,CACX,CAAC,EAEiB,OAAAF,EAAQ,QAAAD,CAAA,CAC5B"}
@@ -0,0 +1,10 @@
1
+ function s() {
2
+ let e, r;
3
+ return { promise: new Promise((o, t) => {
4
+ e = o, r = t;
5
+ }), reject: r, resolve: e };
6
+ }
7
+ export {
8
+ s as defer
9
+ };
10
+ //# sourceMappingURL=defer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defer.js","sources":["../../src/async/defer.ts"],"sourcesContent":["/**\n * Creates a deferred promise with resolve and reject methods exposed.\n * Useful for creating promises that are resolved/rejected externally.\n *\n * @example\n * ```ts\n * const deferred = defer<string>();\n *\n * setTimeout(() => {\n * deferred.resolve('Done!');\n * }, 1000);\n *\n * const result = await deferred.promise; // 'Done!'\n * ```\n *\n * @returns Object with promise and resolve/reject methods\n */\nexport function defer<T = void>(): {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n} {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, reject, resolve };\n}\n"],"names":["defer","resolve","reject","res","rej"],"mappings":"AAiBO,SAASA,IAId;AACA,MAAIC,GACAC;AAOJ,SAAO,EAAE,SALO,IAAI,QAAW,CAACC,GAAKC,MAAQ;AAC3C,IAAAH,IAAUE,GACVD,IAASE;AAAA,EACX,CAAC,GAEiB,QAAAF,GAAQ,SAAAD,EAAA;AAC5B;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delay.cjs","sources":["../../src/async/delay.ts"],"sourcesContent":["import type { Fn } from '../types';\nimport { sleep } from './sleep';\n\n/**\n * Delays the execution of a function by a specified amount of time.\n *\n * @example\n * ```ts\n * const log = () => console.log('Hello, world!');\n *\n * delay(log, 1000); // logs 'Hello, world!' after 1 second\n * ```\n *\n * @param fn - The function to be delayed.\n * @param delay - The amount of time to delay the function execution, in milliseconds. Default is 700.\n *\n * @returns A Promise that resolves with the result of the function execution.\n */\nexport async function delay<T extends Fn>(fn: T, delay = 700) {\n await sleep(delay);\n\n return fn();\n}\n"],"names":["delay","fn","sleep"],"mappings":"+GAkBA,eAAsBA,EAAoBC,EAAOD,EAAQ,IAAK,CAC5D,aAAME,EAAAA,MAAMF,CAAK,EAEVC,EAAA,CACT"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delay.js","sources":["../../src/async/delay.ts"],"sourcesContent":["import type { Fn } from '../types';\nimport { sleep } from './sleep';\n\n/**\n * Delays the execution of a function by a specified amount of time.\n *\n * @example\n * ```ts\n * const log = () => console.log('Hello, world!');\n *\n * delay(log, 1000); // logs 'Hello, world!' after 1 second\n * ```\n *\n * @param fn - The function to be delayed.\n * @param delay - The amount of time to delay the function execution, in milliseconds. Default is 700.\n *\n * @returns A Promise that resolves with the result of the function execution.\n */\nexport async function delay<T extends Fn>(fn: T, delay = 700) {\n await sleep(delay);\n\n return fn();\n}\n"],"names":["delay","fn","sleep"],"mappings":";AAkBA,eAAsBA,EAAoBC,GAAOD,IAAQ,KAAK;AAC5D,eAAME,EAAMF,CAAK,GAEVC,EAAA;AACT;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});async function f(n,r,a,l){if(n<1)throw new Error("Limit must be at least 1");if(l?.aborted)throw new DOMException("Aborted","AbortError");const s=new Array(r.length);let c=0,t=!1,o;const u=()=>l?.aborted?(t=!0,o=new DOMException("Aborted","AbortError"),!0):!1,w=async()=>{for(;c<r.length&&!t&&!u();){const e=c++;try{s[e]=await a(r[e],e,r)}catch(h){t=!0,o=h;break}}},i=[],b=Math.min(n,r.length);for(let e=0;e<b;e++)i.push(w());if(await Promise.all(i),t)throw o;return s}exports.parallel=f;
2
+ //# sourceMappingURL=parallel.cjs.map