@uploadista/core 0.0.20-beta.9 → 0.1.0-beta.5

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 (88) hide show
  1. package/dist/{checksum-DVPe3Db4.cjs → checksum-CTpNXWEL.cjs} +1 -1
  2. package/dist/errors/index.cjs +1 -1
  3. package/dist/errors/index.d.mts +2 -2
  4. package/dist/flow/index.cjs +1 -1
  5. package/dist/flow/index.d.cts +2 -2
  6. package/dist/flow/index.d.mts +6 -6
  7. package/dist/flow/index.mjs +1 -1
  8. package/dist/flow-CA8xO6wP.mjs +2 -0
  9. package/dist/flow-CA8xO6wP.mjs.map +1 -0
  10. package/dist/flow-DKJaCPxL.cjs +1 -0
  11. package/dist/{index-RuQUCROH.d.mts → index-BNhJmMuC.d.mts} +228 -167
  12. package/dist/index-BNhJmMuC.d.mts.map +1 -0
  13. package/dist/{index-DMqaf28W.d.cts → index-BmkhRBV6.d.cts} +226 -165
  14. package/dist/index-BmkhRBV6.d.cts.map +1 -0
  15. package/dist/{index-B9V5SSxl.d.mts → index-D8MZ6P3o.d.mts} +2 -2
  16. package/dist/{index-B9V5SSxl.d.mts.map → index-D8MZ6P3o.d.mts.map} +1 -1
  17. package/dist/{index-BFSHumky.d.mts → index-DQuMQssI.d.mts} +2 -2
  18. package/dist/{index-BFSHumky.d.mts.map → index-DQuMQssI.d.mts.map} +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.d.cts +2 -2
  21. package/dist/index.d.mts +6 -6
  22. package/dist/index.mjs +1 -1
  23. package/dist/{stream-limiter-BvkaZXcz.cjs → stream-limiter-DH0vv46_.cjs} +1 -1
  24. package/dist/streams/index.cjs +1 -1
  25. package/dist/streams/index.d.mts +2 -2
  26. package/dist/streams/index.mjs +1 -1
  27. package/dist/testing/index.cjs +2 -2
  28. package/dist/testing/index.d.cts +1 -1
  29. package/dist/testing/index.d.cts.map +1 -1
  30. package/dist/testing/index.d.mts +5 -5
  31. package/dist/testing/index.d.mts.map +1 -1
  32. package/dist/testing/index.mjs +2 -2
  33. package/dist/testing/index.mjs.map +1 -1
  34. package/dist/types/index.cjs +1 -1
  35. package/dist/types/index.d.cts +2 -2
  36. package/dist/types/index.d.mts +6 -6
  37. package/dist/types/index.mjs +1 -1
  38. package/dist/types-BF_tvkRh.cjs +1 -0
  39. package/dist/types-BRnwrJDg.mjs +2 -0
  40. package/dist/types-BRnwrJDg.mjs.map +1 -0
  41. package/dist/upload/index.cjs +1 -1
  42. package/dist/upload/index.d.cts +1 -1
  43. package/dist/upload/index.d.mts +5 -5
  44. package/dist/upload/index.mjs +1 -1
  45. package/dist/upload-CLHJ1SFS.cjs +1 -0
  46. package/dist/upload-CpsShjP3.mjs +2 -0
  47. package/dist/upload-CpsShjP3.mjs.map +1 -0
  48. package/dist/{uploadista-error-DR0XimpE.d.mts → uploadista-error-B1qbOy9N.d.mts} +1 -1
  49. package/dist/{uploadista-error-DR0XimpE.d.mts.map → uploadista-error-B1qbOy9N.d.mts.map} +1 -1
  50. package/dist/{uploadista-error-BgQU45we.cjs → uploadista-error-CLWoRAAr.cjs} +1 -1
  51. package/dist/uploadista-error-CkSxSyNo.mjs.map +1 -1
  52. package/dist/utils/index.cjs +1 -1
  53. package/dist/utils/index.d.mts +2 -2
  54. package/dist/utils/index.mjs +1 -1
  55. package/dist/{utils-UUJt8ILJ.cjs → utils-CvZJUNEo.cjs} +1 -1
  56. package/dist/{utils-B-ZhQ6b0.mjs → utils-DVwfrVBJ.mjs} +1 -1
  57. package/dist/utils-DVwfrVBJ.mjs.map +1 -0
  58. package/package.json +8 -8
  59. package/src/flow/circuit-breaker-store.ts +7 -8
  60. package/src/flow/flow.ts +6 -5
  61. package/src/flow/nodes/transform-node.ts +15 -1
  62. package/src/flow/plugins/image-plugin.ts +12 -3
  63. package/src/flow/plugins/video-plugin.ts +12 -3
  64. package/src/flow/types/flow-types.ts +75 -6
  65. package/src/flow/types/retry-policy.ts +5 -2
  66. package/src/flow/types/type-utils.ts +4 -6
  67. package/src/flow/utils/file-naming.ts +36 -11
  68. package/src/testing/mock-upload-engine.ts +18 -1
  69. package/src/types/circuit-breaker-store.ts +2 -2
  70. package/src/types/data-store.ts +4 -1
  71. package/src/types/kv-store.ts +13 -12
  72. package/src/types/upload-file.ts +29 -4
  73. package/src/upload/upload-chunk.ts +1 -1
  74. package/dist/flow-BHVkk_6W.cjs +0 -1
  75. package/dist/flow-DlhHOlMk.mjs +0 -2
  76. package/dist/flow-DlhHOlMk.mjs.map +0 -1
  77. package/dist/index-DMqaf28W.d.cts.map +0 -1
  78. package/dist/index-RuQUCROH.d.mts.map +0 -1
  79. package/dist/streams-BiD_pOPH.cjs +0 -0
  80. package/dist/streams-Cqjxk2rI.mjs +0 -1
  81. package/dist/types-Cws60JHC.cjs +0 -1
  82. package/dist/types-DKGQJIEr.mjs +0 -2
  83. package/dist/types-DKGQJIEr.mjs.map +0 -1
  84. package/dist/upload-C-C7hn1-.mjs +0 -2
  85. package/dist/upload-C-C7hn1-.mjs.map +0 -1
  86. package/dist/upload-DWBlRXHh.cjs +0 -1
  87. package/dist/utils-B-ZhQ6b0.mjs.map +0 -1
  88. /package/dist/{index-C-svZlpj.d.mts → index-DWe68pTi.d.mts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-DVwfrVBJ.mjs","names":[],"sources":["../src/utils/md5.ts","../src/utils/once.ts","../src/utils/debounce.ts","../src/utils/throttle.ts"],"sourcesContent":["/*\n\nTypeScript Md5\n==============\n\nBased on work by\n* Joseph Myers: http://www.myersdaily.org/joseph/javascript/md5-text.html\n* André Cruz: https://github.com/satazor/SparkMD5\n* Raymond Hill: https://github.com/gorhill/yamd5.js\n\nEffectively a TypeScrypt re-write of Raymond Hill JS Library\n\nThe MIT License (MIT)\n\nCopyright (C) 2014 Raymond Hill\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n DO WHAT YOU WANT TO PUBLIC LICENSE\n Version 2, December 2004\n\n Copyright (C) 2015 André Cruz <amdfcruz@gmail.com>\n\n Everyone is permitted to copy and distribute verbatim or modified\n copies of this license document, and changing it is allowed as long\n as the name is changed.\n\n DO WHAT YOU WANT TO PUBLIC LICENSE\n TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n 0. You just DO WHAT YOU WANT TO.\n\n*/\n\ntype HasherState = {\n buffer: string;\n buflen: number;\n length: number;\n state: number[];\n};\n\nexport class Md5 {\n /**\n * Hash a UTF-8 string on the spot\n * @param str String to hash\n * @param raw Whether to return the value as an `Int32Array`\n */\n public static hashStr(str: string, raw?: false): string;\n public static hashStr(str: string, raw: true): Int32Array;\n public static hashStr(str: string, raw = false) {\n return Md5.onePassHasher.start().appendStr(str).end(raw);\n }\n\n /**\n * Hash a ASCII string on the spot\n * @param str String to hash\n * @param raw Whether to return the value as an `Int32Array`\n */\n public static hashAsciiStr(str: string, raw?: false): string;\n public static hashAsciiStr(str: string, raw: true): Int32Array;\n public static hashAsciiStr(str: string, raw = false) {\n return Md5.onePassHasher.start().appendAsciiStr(str).end(raw);\n }\n\n // Private Static Variables\n private static stateIdentity = new Int32Array([\n 1732584193, -271733879, -1732584194, 271733878,\n ]);\n\n private static buffer32Identity = new Int32Array([\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n ]);\n\n private static hexChars = \"0123456789abcdef\";\n private static hexOut: string[] = [];\n\n // Permanent instance is to use for one-call hashing\n private static onePassHasher = new Md5();\n\n private static _hex(x: Int32Array): string {\n const hc = Md5.hexChars;\n const ho = Md5.hexOut;\n let n: number;\n let offset: number;\n let j: number;\n let i: number;\n\n for (i = 0; i < 4; i += 1) {\n offset = i * 8;\n n = x[i] ?? 0;\n for (j = 0; j < 8; j += 2) {\n ho[offset + 1 + j] = hc.charAt(n & 0x0f);\n n >>>= 4;\n ho[offset + 0 + j] = hc.charAt(n & 0x0f);\n n >>>= 4;\n }\n }\n return ho.join(\"\");\n }\n\n private static _md5cycle(\n x: Int32Array | Uint32Array,\n k: Int32Array | Uint32Array,\n ) {\n let a: number = x[0] ?? 0;\n let b: number = x[1] ?? 0;\n let c: number = x[2] ?? 0;\n let d: number = x[3] ?? 0;\n // ff()\n a += (((b & c) | (~b & d)) + (k[0] ?? 0) - 680876936) | 0;\n a = (((a << 7) | (a >>> 25)) + b) | 0;\n d += (((a & b) | (~a & c)) + (k[1] ?? 0) - 389564586) | 0;\n d = (((d << 12) | (d >>> 20)) + a) | 0;\n c += (((d & a) | (~d & b)) + (k[2] ?? 0) + 606105819) | 0;\n c = (((c << 17) | (c >>> 15)) + d) | 0;\n b += (((c & d) | (~c & a)) + (k[3] ?? 0) - 1044525330) | 0;\n b = (((b << 22) | (b >>> 10)) + c) | 0;\n a += (((b & c) | (~b & d)) + (k[4] ?? 0) - 176418897) | 0;\n a = (((a << 7) | (a >>> 25)) + b) | 0;\n d += (((a & b) | (~a & c)) + (k[5] ?? 0) + 1200080426) | 0;\n d = (((d << 12) | (d >>> 20)) + a) | 0;\n c += (((d & a) | (~d & b)) + (k[6] ?? 0) - 1473231341) | 0;\n c = (((c << 17) | (c >>> 15)) + d) | 0;\n b += (((c & d) | (~c & a)) + (k[7] ?? 0) - 45705983) | 0;\n b = (((b << 22) | (b >>> 10)) + c) | 0;\n a += (((b & c) | (~b & d)) + (k[8] ?? 0) + 1770035416) | 0;\n a = (((a << 7) | (a >>> 25)) + b) | 0;\n d += (((a & b) | (~a & c)) + (k[9] ?? 0) - 1958414417) | 0;\n d = (((d << 12) | (d >>> 20)) + a) | 0;\n c += (((d & a) | (~d & b)) + (k[10] ?? 0) - 42063) | 0;\n c = (((c << 17) | (c >>> 15)) + d) | 0;\n b += (((c & d) | (~c & a)) + (k[11] ?? 0) - 1990404162) | 0;\n b = (((b << 22) | (b >>> 10)) + c) | 0;\n a += (((b & c) | (~b & d)) + (k[12] ?? 0) + 1804603682) | 0;\n a = (((a << 7) | (a >>> 25)) + b) | 0;\n d += (((a & b) | (~a & c)) + (k[13] ?? 0) - 40341101) | 0;\n d = (((d << 12) | (d >>> 20)) + a) | 0;\n c += (((d & a) | (~d & b)) + (k[14] ?? 0) - 1502002290) | 0;\n c = (((c << 17) | (c >>> 15)) + d) | 0;\n b += (((c & d) | (~c & a)) + (k[15] ?? 0) + 1236535329) | 0;\n b = (((b << 22) | (b >>> 10)) + c) | 0;\n // gg()\n a += (((b & d) | (c & ~d)) + (k[1] ?? 0) - 165796510) | 0;\n a = (((a << 5) | (a >>> 27)) + b) | 0;\n d += (((a & c) | (b & ~c)) + (k[6] ?? 0) - 1069501632) | 0;\n d = (((d << 9) | (d >>> 23)) + a) | 0;\n c += (((d & b) | (a & ~b)) + (k[11] ?? 0) + 643717713) | 0;\n c = (((c << 14) | (c >>> 18)) + d) | 0;\n b += (((c & a) | (d & ~a)) + (k[0] ?? 0) - 373897302) | 0;\n b = (((b << 20) | (b >>> 12)) + c) | 0;\n a += (((b & d) | (c & ~d)) + (k[5] ?? 0) - 701558691) | 0;\n a = (((a << 5) | (a >>> 27)) + b) | 0;\n d += (((a & c) | (b & ~c)) + (k[10] ?? 0) + 38016083) | 0;\n d = (((d << 9) | (d >>> 23)) + a) | 0;\n c += (((d & b) | (a & ~b)) + (k[15] ?? 0) - 660478335) | 0;\n c = (((c << 14) | (c >>> 18)) + d) | 0;\n b += (((c & a) | (d & ~a)) + (k[4] ?? 0) - 405537848) | 0;\n b = (((b << 20) | (b >>> 12)) + c) | 0;\n a += (((b & d) | (c & ~d)) + (k[9] ?? 0) + 568446438) | 0;\n a = (((a << 5) | (a >>> 27)) + b) | 0;\n d += (((a & c) | (b & ~c)) + (k[14] ?? 0) - 1019803690) | 0;\n d = (((d << 9) | (d >>> 23)) + a) | 0;\n c += (((d & b) | (a & ~b)) + (k[3] ?? 0) - 187363961) | 0;\n c = (((c << 14) | (c >>> 18)) + d) | 0;\n b += (((c & a) | (d & ~a)) + (k[8] ?? 0) + 1163531501) | 0;\n b = (((b << 20) | (b >>> 12)) + c) | 0;\n a += (((b & d) | (c & ~d)) + (k[13] ?? 0) - 1444681467) | 0;\n a = (((a << 5) | (a >>> 27)) + b) | 0;\n d += (((a & c) | (b & ~c)) + (k[2] ?? 0) - 51403784) | 0;\n d = (((d << 9) | (d >>> 23)) + a) | 0;\n c += (((d & b) | (a & ~b)) + (k[7] ?? 0) + 1735328473) | 0;\n c = (((c << 14) | (c >>> 18)) + d) | 0;\n b += (((c & a) | (d & ~a)) + (k[12] ?? 0) - 1926607734) | 0;\n b = (((b << 20) | (b >>> 12)) + c) | 0;\n // hh()\n a += ((b ^ c ^ d) + (k[5] ?? 0) - 378558) | 0;\n a = (((a << 4) | (a >>> 28)) + b) | 0;\n d += ((a ^ b ^ c) + (k[8] ?? 0) - 2022574463) | 0;\n d = (((d << 11) | (d >>> 21)) + a) | 0;\n c += ((d ^ a ^ b) + (k[11] ?? 0) + 1839030562) | 0;\n c = (((c << 16) | (c >>> 16)) + d) | 0;\n b += ((c ^ d ^ a) + (k[14] ?? 0) - 35309556) | 0;\n b = (((b << 23) | (b >>> 9)) + c) | 0;\n a += ((b ^ c ^ d) + (k[1] ?? 0) - 1530992060) | 0;\n a = (((a << 4) | (a >>> 28)) + b) | 0;\n d += ((a ^ b ^ c) + (k[4] ?? 0) + 1272893353) | 0;\n d = (((d << 11) | (d >>> 21)) + a) | 0;\n c += ((d ^ a ^ b) + (k[7] ?? 0) - 155497632) | 0;\n c = (((c << 16) | (c >>> 16)) + d) | 0;\n b += ((c ^ d ^ a) + (k[10] ?? 0) - 1094730640) | 0;\n b = (((b << 23) | (b >>> 9)) + c) | 0;\n a += ((b ^ c ^ d) + (k[13] ?? 0) + 681279174) | 0;\n a = (((a << 4) | (a >>> 28)) + b) | 0;\n d += ((a ^ b ^ c) + (k[0] ?? 0) - 358537222) | 0;\n d = (((d << 11) | (d >>> 21)) + a) | 0;\n c += ((d ^ a ^ b) + (k[3] ?? 0) - 722521979) | 0;\n c = (((c << 16) | (c >>> 16)) + d) | 0;\n b += ((c ^ d ^ a) + (k[6] ?? 0) + 76029189) | 0;\n b = (((b << 23) | (b >>> 9)) + c) | 0;\n a += ((b ^ c ^ d) + (k[9] ?? 0) - 640364487) | 0;\n a = (((a << 4) | (a >>> 28)) + b) | 0;\n d += ((a ^ b ^ c) + (k[12] ?? 0) - 421815835) | 0;\n d = (((d << 11) | (d >>> 21)) + a) | 0;\n c += ((d ^ a ^ b) + (k[15] ?? 0) + 530742520) | 0;\n c = (((c << 16) | (c >>> 16)) + d) | 0;\n b += ((c ^ d ^ a) + (k[2] ?? 0) - 995338651) | 0;\n b = (((b << 23) | (b >>> 9)) + c) | 0;\n // ii()\n a += ((c ^ (b | ~d)) + (k[0] ?? 0) - 198630844) | 0;\n a = (((a << 6) | (a >>> 26)) + b) | 0;\n d += ((b ^ (a | ~c)) + (k[7] ?? 0) + 1126891415) | 0;\n d = (((d << 10) | (d >>> 22)) + a) | 0;\n c += ((a ^ (d | ~b)) + (k[14] ?? 0) - 1416354905) | 0;\n c = (((c << 15) | (c >>> 17)) + d) | 0;\n b += ((d ^ (c | ~a)) + (k[5] ?? 0) - 57434055) | 0;\n b = (((b << 21) | (b >>> 11)) + c) | 0;\n a += ((c ^ (b | ~d)) + (k[12] ?? 0) + 1700485571) | 0;\n a = (((a << 6) | (a >>> 26)) + b) | 0;\n d += ((b ^ (a | ~c)) + (k[3] ?? 0) - 1894986606) | 0;\n d = (((d << 10) | (d >>> 22)) + a) | 0;\n c += ((a ^ (d | ~b)) + (k[10] ?? 0) - 1051523) | 0;\n c = (((c << 15) | (c >>> 17)) + d) | 0;\n b += ((d ^ (c | ~a)) + (k[1] ?? 0) - 2054922799) | 0;\n b = (((b << 21) | (b >>> 11)) + c) | 0;\n a += ((c ^ (b | ~d)) + (k[8] ?? 0) + 1873313359) | 0;\n a = (((a << 6) | (a >>> 26)) + b) | 0;\n d += ((b ^ (a | ~c)) + (k[15] ?? 0) - 30611744) | 0;\n d = (((d << 10) | (d >>> 22)) + a) | 0;\n c += ((a ^ (d | ~b)) + (k[6] ?? 0) - 1560198380) | 0;\n c = (((c << 15) | (c >>> 17)) + d) | 0;\n b += ((d ^ (c | ~a)) + (k[13] ?? 0) + 1309151649) | 0;\n b = (((b << 21) | (b >>> 11)) + c) | 0;\n a += ((c ^ (b | ~d)) + (k[4] ?? 0) - 145523070) | 0;\n a = (((a << 6) | (a >>> 26)) + b) | 0;\n d += ((b ^ (a | ~c)) + (k[11] ?? 0) - 1120210379) | 0;\n d = (((d << 10) | (d >>> 22)) + a) | 0;\n c += ((a ^ (d | ~b)) + (k[2] ?? 0) + 718787259) | 0;\n c = (((c << 15) | (c >>> 17)) + d) | 0;\n b += ((d ^ (c | ~a)) + (k[9] ?? 0) - 343485551) | 0;\n b = (((b << 21) | (b >>> 11)) + c) | 0;\n\n x[0] = (a + (x[0] ?? 0)) | 0;\n x[1] = (b + (x[1] ?? 0)) | 0;\n x[2] = (c + (x[2] ?? 0)) | 0;\n x[3] = (d + (x[3] ?? 0)) | 0;\n }\n\n private _dataLength = 0;\n private _bufferLength = 0;\n\n private _state: Int32Array = new Int32Array(4);\n private _buffer: ArrayBuffer = new ArrayBuffer(68);\n private _buffer8: Uint8Array;\n private _buffer32: Uint32Array;\n\n constructor() {\n this._buffer8 = new Uint8Array(this._buffer, 0, 68);\n this._buffer32 = new Uint32Array(this._buffer, 0, 17);\n this.start();\n }\n\n /**\n * Initialise buffer to be hashed\n */\n public start() {\n this._dataLength = 0;\n this._bufferLength = 0;\n this._state.set(Md5.stateIdentity);\n return this;\n }\n\n // Char to code point to to array conversion:\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt\n // #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown\n\n /**\n * Append a UTF-8 string to the hash buffer\n * @param str String to append\n */\n public appendStr(str: string) {\n const buf8 = this._buffer8;\n const buf32 = this._buffer32;\n let bufLen = this._bufferLength;\n let code: number;\n let i: number;\n\n for (i = 0; i < str.length; i += 1) {\n code = str.charCodeAt(i);\n if (code < 128) {\n buf8[bufLen++] = code;\n } else if (code < 0x800) {\n buf8[bufLen++] = (code >>> 6) + 0xc0;\n buf8[bufLen++] = (code & 0x3f) | 0x80;\n } else if (code < 0xd800 || code > 0xdbff) {\n buf8[bufLen++] = (code >>> 12) + 0xe0;\n buf8[bufLen++] = ((code >>> 6) & 0x3f) | 0x80;\n buf8[bufLen++] = (code & 0x3f) | 0x80;\n } else {\n code =\n (code - 0xd800) * 0x400 + (str.charCodeAt(++i) - 0xdc00) + 0x10000;\n if (code > 0x10ffff) {\n throw new Error(\n \"Unicode standard supports code points up to U+10FFFF\",\n );\n }\n buf8[bufLen++] = (code >>> 18) + 0xf0;\n buf8[bufLen++] = ((code >>> 12) & 0x3f) | 0x80;\n buf8[bufLen++] = ((code >>> 6) & 0x3f) | 0x80;\n buf8[bufLen++] = (code & 0x3f) | 0x80;\n }\n if (bufLen >= 64) {\n this._dataLength += 64;\n Md5._md5cycle(this._state, buf32);\n bufLen -= 64;\n buf32[0] = buf32[16] ?? 0;\n }\n }\n this._bufferLength = bufLen;\n return this;\n }\n\n /**\n * Append an ASCII string to the hash buffer\n * @param str String to append\n */\n public appendAsciiStr(str: string) {\n const buf8 = this._buffer8;\n const buf32 = this._buffer32;\n let bufLen = this._bufferLength;\n let i: number;\n let j = 0;\n\n for (;;) {\n i = Math.min(str.length - j, 64 - bufLen);\n while (i--) {\n buf8[bufLen++] = str.charCodeAt(j++);\n }\n if (bufLen < 64) {\n break;\n }\n this._dataLength += 64;\n Md5._md5cycle(this._state, buf32);\n bufLen = 0;\n }\n this._bufferLength = bufLen;\n return this;\n }\n\n /**\n * Append a byte array to the hash buffer\n * @param input array to append\n */\n public appendByteArray(input: Uint8Array) {\n const buf8 = this._buffer8;\n const buf32 = this._buffer32;\n let bufLen = this._bufferLength;\n let i: number;\n let j = 0;\n\n for (;;) {\n i = Math.min(input.length - j, 64 - bufLen);\n while (i--) {\n buf8[bufLen++] = input[j++] ?? 0;\n }\n if (bufLen < 64) {\n break;\n }\n this._dataLength += 64;\n Md5._md5cycle(this._state, buf32);\n bufLen = 0;\n }\n this._bufferLength = bufLen;\n return this;\n }\n\n /**\n * Get the state of the hash buffer\n */\n public getState(): HasherState {\n const s = this._state;\n\n return {\n buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)),\n buflen: this._bufferLength,\n length: this._dataLength,\n state: [s[0] ?? 0, s[1] ?? 0, s[2] ?? 0, s[3] ?? 0],\n };\n }\n\n /**\n * Override the current state of the hash buffer\n * @param state New hash buffer state\n */\n public setState(state: HasherState) {\n const buf = state.buffer;\n const x = state.state;\n const s = this._state;\n let i: number;\n\n this._dataLength = state.length;\n this._bufferLength = state.buflen;\n s[0] = x[0] ?? 0;\n s[1] = x[1] ?? 0;\n s[2] = x[2] ?? 0;\n s[3] = x[3] ?? 0;\n\n for (i = 0; i < buf.length; i += 1) {\n this._buffer8[i] = buf.charCodeAt(i);\n }\n }\n\n /**\n * Hash the current state of the hash buffer and return the result\n * @param raw Whether to return the value as an `Int32Array`\n */\n public end(raw = false) {\n const bufLen = this._bufferLength;\n const buf8 = this._buffer8;\n const buf32 = this._buffer32;\n const i = (bufLen >> 2) + 1;\n\n this._dataLength += bufLen;\n const dataBitsLen = this._dataLength * 8;\n\n buf8[bufLen] = 0x80;\n buf8[bufLen + 1] = buf8[bufLen + 2] = buf8[bufLen + 3] = 0;\n buf32.set(Md5.buffer32Identity.subarray(i), i);\n\n if (bufLen > 55) {\n Md5._md5cycle(this._state, buf32);\n buf32.set(Md5.buffer32Identity);\n }\n\n // Do the final computation based on the tail and length\n // Beware that the final length may not fit in 32 bits so we take care of that\n if (dataBitsLen <= 0xffffffff) {\n buf32[14] = dataBitsLen;\n } else {\n const matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/);\n if (matches === null) {\n return;\n }\n\n const lo = Number.parseInt(matches[2] ?? \"\", 16);\n const hi = Number.parseInt(matches[1] ?? \"\", 16) || 0;\n\n buf32[14] = lo;\n buf32[15] = hi;\n }\n\n Md5._md5cycle(this._state, buf32);\n\n return raw ? this._state : Md5._hex(this._state);\n }\n}\n\nif (Md5.hashStr(\"hello\") !== \"5d41402abc4b2a76b9719d911017c592\") {\n throw new Error(\"Md5 self test failed.\");\n}\n","import { Effect } from \"effect\";\nimport { UploadistaError } from \"../errors/uploadista-error\";\n\n// only call a function once\nexport function once<T, A extends unknown[], Return>(\n fn: (this: T, ...args: A) => Return,\n) {\n let called = false;\n let value: Return | undefined;\n const f = function (this: T, ...args: A): Return {\n if (called) {\n if (value) {\n return value;\n }\n throw new Error(\"Function called more than once\");\n }\n called = true;\n value = fn.apply(this, args);\n return value;\n };\n return f;\n}\n\n/**\n * Effect-based once utilities\n */\nexport const OnceEffect = {\n /**\n * Creates an Effect-based once function that only executes once\n * @param effect - The effect to execute only once\n * @returns Effect that caches the result after first execution\n */\n make: <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n ): Effect.Effect<A, E | UploadistaError, R> => {\n let cached: A | undefined;\n let called = false;\n\n return Effect.gen(function* () {\n if (called) {\n if (cached !== undefined) {\n return cached;\n }\n yield* new UploadistaError({\n code: \"UNKNOWN_ERROR\",\n status: 500,\n body: \"Effect called more than once with undefined result\",\n }).toEffect();\n }\n\n called = true;\n cached = yield* effect;\n return cached;\n });\n },\n\n /**\n * Creates a legacy once function wrapper\n * @param fn - Function to wrap\n * @returns Once-wrapped function\n */\n legacy: once,\n};\n","type DebounceOptions = {\n // Whether the first call to the debounced function is run immediately.\n leading?: boolean;\n\n // Whether the last call to the debounced function is run after delay\n // milliseconds have elapsed since the last call.\n trailing?: boolean;\n};\n\nconst defaultDebounceOptions: DebounceOptions = {\n leading: false,\n trailing: true,\n};\n\n/**\n * Returns `fn` wrapped by a function that delays invoking `fn` for `delay`\n * milliseconds since the last call. Set `options.leading` to invoke `fn` on\n * the leading edge of the delay, and/or set `options.trailing` to invoke `fn`\n * on the trailing edge of the delay (true by default).\n *\n * Example for `debounce(fn, 30, {leading: true, trailing: true})`,\n * where `fn` is called twice, with the second call made 20 ms after the first:\n *\n * Time: 0 20 50 (ms)\n * Timeline: |----------------------------------------------------------------|\n * ^ ^ ^\n * | | |\n * | First call. | Second call 20ms after the | End of delay.\n * | (instant leading | first. | (trailing edge\n * | edge call) | | call)\n * |-----------------------------|\n * | 30 ms delay for debounce. |\n *\n *\n * Note that if both `options.leading` and `options.trailing` are true, `fn`\n * will only be invoked on the trailing edge if the debounced function is called\n * more than once during the delay.\n *\n * @param fn - Function to debounce.\n * @param delay - Milliseconds to delay calling `fn` since the last call.\n * @param debounceOptions - See `DebounceOptions` and `defaultDebounceOptions`.\n * @returns A debounced `fn`.\n */\nexport function debounce<T, A extends unknown[]>(\n fn: (this: T, ...args: A) => void,\n delay: number,\n debounceOptions: DebounceOptions = {},\n): (this: T, ...args: A) => void {\n const options = { ...defaultDebounceOptions, ...debounceOptions };\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n return function (this: T, ...args: A): void {\n if (options.leading && !timer) {\n // Leading edge.\n // Call fn on the leading edge, when debouncing hasn't started yet.\n console.log(\"leading\");\n fn.apply(this, args);\n\n // Debounce the next call.\n timer = setTimeout(() => {\n timer = undefined;\n }, delay);\n } else {\n // Trailing edge.\n // Postpone calling fn until the delay has elapsed since the last call.\n // Each call clears any previously delayed call and resets the delay, so\n // the postponed call will always be the last one.\n clearTimeout(timer);\n timer = setTimeout(() => {\n if (options.trailing) {\n // Call fn on the trailing edge.\n fn.apply(this, args);\n\n if (options.leading) {\n // Debounce next leading call since a trailing call was just made.\n setTimeout(() => {\n timer = undefined;\n }, delay);\n }\n } else {\n // No trailing call. Since the delay has elapsed since the last call,\n // immediately reset the debouncing delay.\n timer = undefined;\n }\n }, delay);\n }\n };\n}\n","import { debounce } from \"./debounce.js\";\n\nexport function throttle<T, A extends unknown[], Return>(\n fn: (this: T, ...args: A) => Return,\n wait: number,\n {\n leading = true,\n trailing = true,\n }: { leading?: boolean; trailing?: boolean } = {},\n) {\n return debounce(fn, wait, {\n leading,\n trailing,\n });\n}\n\n/**\n * Effect-based throttle utilities\n */\nexport const ThrottleEffect = {\n /**\n * Creates a legacy throttle function wrapper\n * @param fn - Function to throttle\n * @param wait - Wait time in milliseconds\n * @param options - Throttle options\n * @returns Throttled function\n */\n legacy: throttle,\n};\n"],"mappings":"oFAyDA,IAAa,EAAb,MAAa,CAAI,CAQf,OAAc,QAAQ,EAAa,EAAM,GAAO,CAC9C,OAAO,EAAI,cAAc,OAAO,CAAC,UAAU,EAAI,CAAC,IAAI,EAAI,CAU1D,OAAc,aAAa,EAAa,EAAM,GAAO,CACnD,OAAO,EAAI,cAAc,OAAO,CAAC,eAAe,EAAI,CAAC,IAAI,EAAI,CAI/D,OAAe,cAAgB,IAAI,WAAW,CAC5C,WAAY,WAAY,YAAa,UACtC,CAAC,CAEF,OAAe,iBAAmB,IAAI,WAAW,CAC/C,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAC9C,CAAC,CAEF,OAAe,SAAW,mBAC1B,OAAe,OAAmB,EAAE,CAGpC,OAAe,cAAgB,IAAI,EAEnC,OAAe,KAAK,EAAuB,CACzC,IAAM,EAAK,EAAI,SACT,EAAK,EAAI,OACX,EACA,EACA,EACA,EAEJ,IAAK,EAAI,EAAG,EAAI,EAAG,GAAK,EAGtB,IAFA,EAAS,EAAI,EACb,EAAI,EAAE,IAAM,EACP,EAAI,EAAG,EAAI,EAAG,GAAK,EACtB,EAAG,EAAS,EAAI,GAAK,EAAG,OAAO,EAAI,GAAK,CACxC,KAAO,EACP,EAAG,EAAS,EAAI,GAAK,EAAG,OAAO,EAAI,GAAK,CACxC,KAAO,EAGX,OAAO,EAAG,KAAK,GAAG,CAGpB,OAAe,UACb,EACA,EACA,CACA,IAAI,EAAY,EAAE,IAAM,EACpB,EAAY,EAAE,IAAM,EACpB,EAAY,EAAE,IAAM,EACpB,EAAY,EAAE,IAAM,EAExB,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,SAAY,EACvD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,MAAS,EACrD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,SAAY,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,CAAC,EAAI,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EAErC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,UAAa,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,SAAY,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,UAAa,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,UAAa,EACxD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,SAAY,EACvD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,IAAM,GAAK,WAAc,EACzD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAQ,EAAI,EAAM,EAAI,CAAC,IAAO,EAAE,KAAO,GAAK,WAAc,EAC1D,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EAErC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,OAAU,EAC5C,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,WAAc,EAChD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,WAAc,EACjD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,SAAY,EAC/C,GAAO,GAAK,GAAO,IAAM,GAAM,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,WAAc,EAChD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,WAAc,EAChD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,UAAa,EAC/C,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,WAAc,EACjD,GAAO,GAAK,GAAO,IAAM,GAAM,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,UAAa,EAChD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,UAAa,EAC/C,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,UAAa,EAC/C,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,SAAY,EAC9C,GAAO,GAAK,GAAO,IAAM,GAAM,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,UAAa,EAC/C,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,UAAa,EAChD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,KAAO,GAAK,UAAa,EAChD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,EAAI,EAAI,IAAM,EAAE,IAAM,GAAK,UAAa,EAC/C,GAAO,GAAK,GAAO,IAAM,GAAM,EAAK,EAEpC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,UAAa,EAClD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,WAAc,EACnD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,WAAc,EACpD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,SAAY,EACjD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,WAAc,EACpD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,WAAc,EACnD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,QAAW,EACjD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,WAAc,EACnD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,WAAc,EACnD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,SAAY,EAClD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,WAAc,EACnD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,WAAc,EACpD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,UAAa,EAClD,GAAO,GAAK,EAAM,IAAM,IAAO,EAAK,EACpC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,KAAO,GAAK,WAAc,EACpD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,UAAa,EAClD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EACrC,IAAO,GAAK,EAAI,CAAC,KAAO,EAAE,IAAM,GAAK,UAAa,EAClD,GAAO,GAAK,GAAO,IAAM,IAAO,EAAK,EAErC,EAAE,GAAM,GAAK,EAAE,IAAM,GAAM,EAC3B,EAAE,GAAM,GAAK,EAAE,IAAM,GAAM,EAC3B,EAAE,GAAM,GAAK,EAAE,IAAM,GAAM,EAC3B,EAAE,GAAM,GAAK,EAAE,IAAM,GAAM,EAG7B,YAAsB,EACtB,cAAwB,EAExB,OAA6B,IAAI,WAAW,EAAE,CAC9C,QAA+B,IAAI,YAAY,GAAG,CAClD,SACA,UAEA,aAAc,CACZ,KAAK,SAAW,IAAI,WAAW,KAAK,QAAS,EAAG,GAAG,CACnD,KAAK,UAAY,IAAI,YAAY,KAAK,QAAS,EAAG,GAAG,CACrD,KAAK,OAAO,CAMd,OAAe,CAIb,MAHA,MAAK,YAAc,EACnB,KAAK,cAAgB,EACrB,KAAK,OAAO,IAAI,EAAI,cAAc,CAC3B,KAWT,UAAiB,EAAa,CAC5B,IAAM,EAAO,KAAK,SACZ,EAAQ,KAAK,UACf,EAAS,KAAK,cACd,EACA,EAEJ,IAAK,EAAI,EAAG,EAAI,EAAI,OAAQ,GAAK,EAAG,CAElC,GADA,EAAO,EAAI,WAAW,EAAE,CACpB,EAAO,IACT,EAAK,KAAY,UACR,EAAO,KAChB,EAAK,MAAa,IAAS,GAAK,IAChC,EAAK,KAAa,EAAO,GAAQ,YACxB,EAAO,OAAU,EAAO,MACjC,EAAK,MAAa,IAAS,IAAM,IACjC,EAAK,KAAc,IAAS,EAAK,GAAQ,IACzC,EAAK,KAAa,EAAO,GAAQ,QAC5B,CAGL,GAFA,GACG,EAAO,OAAU,MAAS,EAAI,WAAW,EAAE,EAAE,CAAG,OAAU,MACzD,EAAO,QACT,MAAU,MACR,uDACD,CAEH,EAAK,MAAa,IAAS,IAAM,IACjC,EAAK,KAAc,IAAS,GAAM,GAAQ,IAC1C,EAAK,KAAc,IAAS,EAAK,GAAQ,IACzC,EAAK,KAAa,EAAO,GAAQ,IAE/B,GAAU,KACZ,KAAK,aAAe,GACpB,EAAI,UAAU,KAAK,OAAQ,EAAM,CACjC,GAAU,GACV,EAAM,GAAK,EAAM,KAAO,GAI5B,MADA,MAAK,cAAgB,EACd,KAOT,eAAsB,EAAa,CACjC,IAAM,EAAO,KAAK,SACZ,EAAQ,KAAK,UACf,EAAS,KAAK,cACd,EACA,EAAI,EAER,OAAS,CAEP,IADA,EAAI,KAAK,IAAI,EAAI,OAAS,EAAG,GAAK,EAAO,CAClC,KACL,EAAK,KAAY,EAAI,WAAW,IAAI,CAEtC,GAAI,EAAS,GACX,MAEF,KAAK,aAAe,GACpB,EAAI,UAAU,KAAK,OAAQ,EAAM,CACjC,EAAS,EAGX,MADA,MAAK,cAAgB,EACd,KAOT,gBAAuB,EAAmB,CACxC,IAAM,EAAO,KAAK,SACZ,EAAQ,KAAK,UACf,EAAS,KAAK,cACd,EACA,EAAI,EAER,OAAS,CAEP,IADA,EAAI,KAAK,IAAI,EAAM,OAAS,EAAG,GAAK,EAAO,CACpC,KACL,EAAK,KAAY,EAAM,MAAQ,EAEjC,GAAI,EAAS,GACX,MAEF,KAAK,aAAe,GACpB,EAAI,UAAU,KAAK,OAAQ,EAAM,CACjC,EAAS,EAGX,MADA,MAAK,cAAgB,EACd,KAMT,UAA+B,CAC7B,IAAM,EAAI,KAAK,OAEf,MAAO,CACL,OAAQ,OAAO,aAAa,MAAM,KAAM,MAAM,KAAK,KAAK,SAAS,CAAC,CAClE,OAAQ,KAAK,cACb,OAAQ,KAAK,YACb,MAAO,CAAC,EAAE,IAAM,EAAG,EAAE,IAAM,EAAG,EAAE,IAAM,EAAG,EAAE,IAAM,EAAE,CACpD,CAOH,SAAgB,EAAoB,CAClC,IAAM,EAAM,EAAM,OACZ,EAAI,EAAM,MACV,EAAI,KAAK,OACX,EASJ,IAPA,KAAK,YAAc,EAAM,OACzB,KAAK,cAAgB,EAAM,OAC3B,EAAE,GAAK,EAAE,IAAM,EACf,EAAE,GAAK,EAAE,IAAM,EACf,EAAE,GAAK,EAAE,IAAM,EACf,EAAE,GAAK,EAAE,IAAM,EAEV,EAAI,EAAG,EAAI,EAAI,OAAQ,GAAK,EAC/B,KAAK,SAAS,GAAK,EAAI,WAAW,EAAE,CAQxC,IAAW,EAAM,GAAO,CACtB,IAAM,EAAS,KAAK,cACd,EAAO,KAAK,SACZ,EAAQ,KAAK,UACb,GAAK,GAAU,GAAK,EAE1B,KAAK,aAAe,EACpB,IAAM,EAAc,KAAK,YAAc,EAavC,GAXA,EAAK,GAAU,IACf,EAAK,EAAS,GAAK,EAAK,EAAS,GAAK,EAAK,EAAS,GAAK,EACzD,EAAM,IAAI,EAAI,iBAAiB,SAAS,EAAE,CAAE,EAAE,CAE1C,EAAS,KACX,EAAI,UAAU,KAAK,OAAQ,EAAM,CACjC,EAAM,IAAI,EAAI,iBAAiB,EAK7B,GAAe,WACjB,EAAM,IAAM,MACP,CACL,IAAM,EAAU,EAAY,SAAS,GAAG,CAAC,MAAM,iBAAiB,CAChE,GAAI,IAAY,KACd,OAGF,IAAM,EAAK,OAAO,SAAS,EAAQ,IAAM,GAAI,GAAG,CAC1C,EAAK,OAAO,SAAS,EAAQ,IAAM,GAAI,GAAG,EAAI,EAEpD,EAAM,IAAM,EACZ,EAAM,IAAM,EAKd,OAFA,EAAI,UAAU,KAAK,OAAQ,EAAM,CAE1B,EAAM,KAAK,OAAS,EAAI,KAAK,KAAK,OAAO,GAIpD,GAAI,EAAI,QAAQ,QAAQ,GAAK,mCAC3B,MAAU,MAAM,wBAAwB,CCrd1C,SAAgB,EACd,EACA,CACA,IAAI,EAAS,GACT,EAYJ,OAXU,SAAmB,GAAG,EAAiB,CAC/C,GAAI,EAAQ,CACV,GAAI,EACF,OAAO,EAET,MAAU,MAAM,iCAAiC,CAInD,MAFA,GAAS,GACT,EAAQ,EAAG,MAAM,KAAM,EAAK,CACrB,GAQX,MAAa,EAAa,CAMxB,KACE,GAC6C,CAC7C,IAAI,EACA,EAAS,GAEb,OAAO,EAAO,IAAI,WAAa,CAC7B,GAAI,EAAQ,CACV,GAAI,IAAW,IAAA,GACb,OAAO,EAET,MAAO,IAAI,EAAgB,CACzB,KAAM,gBACN,OAAQ,IACR,KAAM,qDACP,CAAC,CAAC,UAAU,CAKf,MAFA,GAAS,GACT,EAAS,MAAO,EACT,GACP,EAQJ,OAAQ,EACT,CCrDK,EAA0C,CAC9C,QAAS,GACT,SAAU,GACX,CA+BD,SAAgB,EACd,EACA,EACA,EAAmC,EAAE,CACN,CAC/B,IAAM,EAAU,CAAE,GAAG,EAAwB,GAAG,EAAiB,CAE7D,EAEJ,OAAO,SAAmB,GAAG,EAAe,CACtC,EAAQ,SAAW,CAAC,GAGtB,QAAQ,IAAI,UAAU,CACtB,EAAG,MAAM,KAAM,EAAK,CAGpB,EAAQ,eAAiB,CACvB,EAAQ,IAAA,IACP,EAAM,GAMT,aAAa,EAAM,CACnB,EAAQ,eAAiB,CACnB,EAAQ,UAEV,EAAG,MAAM,KAAM,EAAK,CAEhB,EAAQ,SAEV,eAAiB,CACf,EAAQ,IAAA,IACP,EAAM,EAKX,EAAQ,IAAA,IAET,EAAM,GCnFf,SAAgB,EACd,EACA,EACA,CACE,UAAU,GACV,WAAW,IACkC,EAAE,CACjD,CACA,OAAO,EAAS,EAAI,EAAM,CACxB,UACA,WACD,CAAC,CAMJ,MAAa,EAAiB,CAQ5B,OAAQ,EACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uploadista/core",
3
- "version": "0.0.20-beta.9",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "Core package of Uploadista",
5
5
  "license": "MIT",
6
6
  "author": "Uploadista",
@@ -71,13 +71,13 @@
71
71
  },
72
72
  "devDependencies": {
73
73
  "@effect/vitest": "0.27.0",
74
- "@types/node": "24.10.4",
75
- "effect": "3.19.12",
74
+ "@types/node": "24.10.8",
75
+ "effect": "3.19.14",
76
76
  "tsd": "0.33.0",
77
- "tsdown": "0.18.0",
78
- "vitest": "4.0.15",
79
- "zod": "4.2.0",
80
- "@uploadista/typescript-config": "0.0.20-beta.9"
77
+ "tsdown": "0.19.0",
78
+ "vitest": "4.0.17",
79
+ "zod": "4.3.5",
80
+ "@uploadista/typescript-config": "0.1.0-beta.5"
81
81
  },
82
82
  "publishConfig": {
83
83
  "access": "public",
@@ -90,7 +90,7 @@
90
90
  "format": "biome format --write ./src",
91
91
  "lint": "biome lint --write ./src",
92
92
  "check": "biome check --write ./src",
93
- "test": "vitest",
93
+ "test": "vitest run",
94
94
  "test:run": "vitest run",
95
95
  "test:watch": "vitest --watch",
96
96
  "typecheck": "tsc --noEmit"
@@ -9,12 +9,7 @@
9
9
 
10
10
  import { Effect, Layer } from "effect";
11
11
 
12
- import { UploadistaError } from "../errors";
13
- import {
14
- type BaseKvStore,
15
- BaseKvStoreService,
16
- jsonSerializer,
17
- } from "../types/kv-store";
12
+ import type { UploadistaError } from "../errors";
18
13
  import {
19
14
  type CircuitBreakerStateData,
20
15
  type CircuitBreakerStats,
@@ -22,6 +17,11 @@ import {
22
17
  CircuitBreakerStoreService,
23
18
  createInitialCircuitBreakerState,
24
19
  } from "../types/circuit-breaker-store";
20
+ import {
21
+ type BaseKvStore,
22
+ BaseKvStoreService,
23
+ jsonSerializer,
24
+ } from "../types/kv-store";
25
25
 
26
26
  // ============================================================================
27
27
  // Key Prefix
@@ -231,8 +231,7 @@ export function makeMemoryCircuitBreakerStore(): CircuitBreakerStore {
231
231
  const store = new Map<string, CircuitBreakerStateData>();
232
232
 
233
233
  return {
234
- getState: (nodeType: string) =>
235
- Effect.succeed(store.get(nodeType) ?? null),
234
+ getState: (nodeType: string) => Effect.succeed(store.get(nodeType) ?? null),
236
235
 
237
236
  setState: (nodeType: string, state: CircuitBreakerStateData) =>
238
237
  Effect.sync(() => {
package/src/flow/flow.ts CHANGED
@@ -890,9 +890,9 @@ export function createFlowWithSchema<
890
890
  });
891
891
 
892
892
  // Support both Effect and Promise
893
- result = yield* (Effect.isEffect(hookResult)
893
+ result = yield* Effect.isEffect(hookResult)
894
894
  ? hookResult
895
- : Effect.promise(() => hookResult as Promise<unknown>));
895
+ : Effect.promise(() => hookResult as Promise<unknown>);
896
896
  }
897
897
  }
898
898
 
@@ -1040,9 +1040,10 @@ export function createFlowWithSchema<
1040
1040
  const circuitBreakerStore = yield* Effect.serviceOption(
1041
1041
  CircuitBreakerStoreService,
1042
1042
  );
1043
- const circuitBreakerRegistry = circuitBreakerStore._tag === "Some"
1044
- ? new DistributedCircuitBreakerRegistry(circuitBreakerStore.value)
1045
- : null;
1043
+ const circuitBreakerRegistry =
1044
+ circuitBreakerStore._tag === "Some"
1045
+ ? new DistributedCircuitBreakerRegistry(circuitBreakerStore.value)
1046
+ : null;
1046
1047
 
1047
1048
  // Emit FlowStart event only if starting fresh
1048
1049
  if (!resumeFrom && onEvent) {
@@ -111,7 +111,13 @@ export interface TransformNodeConfig {
111
111
  bytes: Uint8Array,
112
112
  file: UploadFile,
113
113
  ) => Effect.Effect<
114
- Uint8Array | { bytes: Uint8Array; type?: string; fileName?: string },
114
+ | Uint8Array
115
+ | {
116
+ bytes: Uint8Array;
117
+ type?: string;
118
+ fileName?: string;
119
+ metadata?: Record<string, unknown>;
120
+ },
115
121
  UploadistaError
116
122
  >;
117
123
  /**
@@ -470,6 +476,12 @@ export function createTransformNode({
470
476
  ? undefined
471
477
  : transformResult.fileName;
472
478
 
479
+ // Get metadata from transform result if provided
480
+ const outputMetadata =
481
+ transformResult instanceof Uint8Array
482
+ ? undefined
483
+ : transformResult.metadata;
484
+
473
485
  // Apply file naming if configured and no explicit fileName from transform
474
486
  if (!outputFileName && naming) {
475
487
  const namingContext = buildNamingContext(
@@ -513,6 +525,8 @@ export function createTransformNode({
513
525
  const updatedMetadata = metadata
514
526
  ? {
515
527
  ...metadata,
528
+ // Merge transform-returned metadata (e.g., virusScan results)
529
+ ...outputMetadata,
516
530
  // Update mimeType and related fields if type changed
517
531
  ...(outputType && {
518
532
  mimeType: outputType,
@@ -105,7 +105,10 @@ export type ImagePluginShape = {
105
105
  optimizeStream?: (
106
106
  input: Stream.Stream<Uint8Array, UploadistaError>,
107
107
  options: OptimizeParams,
108
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
108
+ ) => Effect.Effect<
109
+ Stream.Stream<Uint8Array, UploadistaError>,
110
+ UploadistaError
111
+ >;
109
112
 
110
113
  /**
111
114
  * Resizes an image using streaming for memory-efficient processing of large files.
@@ -136,7 +139,10 @@ export type ImagePluginShape = {
136
139
  resizeStream?: (
137
140
  input: Stream.Stream<Uint8Array, UploadistaError>,
138
141
  options: ResizeParams,
139
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
142
+ ) => Effect.Effect<
143
+ Stream.Stream<Uint8Array, UploadistaError>,
144
+ UploadistaError
145
+ >;
140
146
 
141
147
  /**
142
148
  * Applies a single transformation using streaming for memory-efficient processing.
@@ -166,7 +172,10 @@ export type ImagePluginShape = {
166
172
  transformStream?: (
167
173
  input: Stream.Stream<Uint8Array, UploadistaError>,
168
174
  transformation: Transformation,
169
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
175
+ ) => Effect.Effect<
176
+ Stream.Stream<Uint8Array, UploadistaError>,
177
+ UploadistaError
178
+ >;
170
179
 
171
180
  /**
172
181
  * Indicates whether this plugin supports streaming operations.
@@ -124,7 +124,10 @@ export type VideoPluginShape = {
124
124
  input: VideoStreamInput,
125
125
  options: TranscodeVideoParams,
126
126
  streamOptions?: VideoStreamOptions,
127
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
127
+ ) => Effect.Effect<
128
+ Stream.Stream<Uint8Array, UploadistaError>,
129
+ UploadistaError
130
+ >;
128
131
 
129
132
  /**
130
133
  * Resizes a video using streaming for memory-efficient processing of large files.
@@ -157,7 +160,10 @@ export type VideoPluginShape = {
157
160
  input: VideoStreamInput,
158
161
  options: ResizeVideoParams,
159
162
  streamOptions?: VideoStreamOptions,
160
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
163
+ ) => Effect.Effect<
164
+ Stream.Stream<Uint8Array, UploadistaError>,
165
+ UploadistaError
166
+ >;
161
167
 
162
168
  /**
163
169
  * Trims a video using streaming for memory-efficient processing of large files.
@@ -189,7 +195,10 @@ export type VideoPluginShape = {
189
195
  input: VideoStreamInput,
190
196
  options: TrimVideoParams,
191
197
  streamOptions?: VideoStreamOptions,
192
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
198
+ ) => Effect.Effect<
199
+ Stream.Stream<Uint8Array, UploadistaError>,
200
+ UploadistaError
201
+ >;
193
202
 
194
203
  /**
195
204
  * Indicates whether this plugin supports streaming operations.
@@ -56,6 +56,12 @@ export type FlowNodeData = {
56
56
  nodeTypeId?: string;
57
57
  };
58
58
 
59
+ /**
60
+ * All built-in node type identifiers.
61
+ * Used to exclude these from custom types for proper discriminated union narrowing.
62
+ */
63
+ export type BuiltInNodeType = "storage-output-v1" | "streaming-input-v1";
64
+
59
65
  /**
60
66
  * Built-in typed outputs with automatic TypeScript narrowing.
61
67
  *
@@ -72,12 +78,19 @@ export type FlowNodeData = {
72
78
  * }
73
79
  * ```
74
80
  */
75
- export type BuiltInTypedOutput = {
76
- nodeType: "storage-output-v1";
77
- data: UploadFile;
78
- nodeId: string;
79
- timestamp: string;
80
- };
81
+ export type BuiltInTypedOutput =
82
+ | {
83
+ nodeType: "storage-output-v1";
84
+ data: UploadFile;
85
+ nodeId: string;
86
+ timestamp: string;
87
+ }
88
+ | {
89
+ nodeType: "streaming-input-v1";
90
+ data: UploadFile;
91
+ nodeId: string;
92
+ timestamp: string;
93
+ };
81
94
 
82
95
  /**
83
96
  * Custom typed output for user-defined node types.
@@ -179,6 +192,62 @@ export type TypedOutput<T = unknown> =
179
192
  | BuiltInTypedOutput
180
193
  | CustomTypedOutput<T>;
181
194
 
195
+ /**
196
+ * Helper type to extract a specific built-in output by nodeType.
197
+ *
198
+ * This enables type-safe narrowing when you know the nodeType:
199
+ * ```typescript
200
+ * if (output.nodeType === "storage-output-v1") {
201
+ * const narrowed = output as NarrowTypedOutput<"storage-output-v1">;
202
+ * narrowed.data.url; // ✅ TypeScript knows data is UploadFile
203
+ * }
204
+ * ```
205
+ */
206
+ export type NarrowTypedOutput<NodeType extends BuiltInNodeType> = Extract<
207
+ BuiltInTypedOutput,
208
+ { nodeType: NodeType }
209
+ >;
210
+
211
+ /**
212
+ * Type guard function signature for narrowing TypedOutput.
213
+ *
214
+ * @template NodeType - The built-in node type to narrow to
215
+ */
216
+ export type TypedOutputGuard<NodeType extends BuiltInNodeType> = (
217
+ output: TypedOutput,
218
+ ) => output is NarrowTypedOutput<NodeType>;
219
+
220
+ /**
221
+ * Creates a type-safe type guard for a built-in node type.
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const isStorageV1 = createOutputGuard("storage-output-v1");
226
+ *
227
+ * for (const output of outputs) {
228
+ * if (isStorageV1(output)) {
229
+ * output.data.url; // ✅ TypeScript knows data is UploadFile
230
+ * }
231
+ * }
232
+ * ```
233
+ */
234
+ export const createOutputGuard =
235
+ <NodeType extends BuiltInNodeType>(
236
+ nodeType: NodeType,
237
+ ): TypedOutputGuard<NodeType> =>
238
+ (output: TypedOutput): output is NarrowTypedOutput<NodeType> =>
239
+ output.nodeType === nodeType;
240
+
241
+ /**
242
+ * Pre-built type guard for storage-output-v1.
243
+ */
244
+ export const isStorageOutputV1 = createOutputGuard("storage-output-v1");
245
+
246
+ /**
247
+ * Pre-built type guard for streaming-input-v1.
248
+ */
249
+ export const isStreamingInputV1 = createOutputGuard("streaming-input-v1");
250
+
182
251
  /**
183
252
  * Result of a node execution - either complete or waiting for more data.
184
253
  *
@@ -74,7 +74,10 @@ export interface ExponentialBackoff {
74
74
  /**
75
75
  * Union type for all backoff strategies.
76
76
  */
77
- export type BackoffStrategy = ImmediateBackoff | FixedBackoff | ExponentialBackoff;
77
+ export type BackoffStrategy =
78
+ | ImmediateBackoff
79
+ | FixedBackoff
80
+ | ExponentialBackoff;
78
81
 
79
82
  /**
80
83
  * Configuration for automatic retry behavior.
@@ -182,7 +185,7 @@ export function calculateBackoffDelay(
182
185
 
183
186
  case "exponential": {
184
187
  const baseDelay =
185
- backoff.initialDelayMs * Math.pow(backoff.multiplier, retryCount);
188
+ backoff.initialDelayMs * backoff.multiplier ** retryCount;
186
189
  const cappedDelay = Math.min(baseDelay, backoff.maxDelayMs);
187
190
 
188
191
  if (backoff.jitter) {
@@ -110,9 +110,8 @@ export type ExtractLayerServices<
110
110
  * ```
111
111
  */
112
112
  // biome-ignore lint/suspicious/noExplicitAny: Utility type needs to handle any Effect type parameters
113
- export type ResolveEffect<T> = T extends Effect.Effect<infer S, any, any>
114
- ? S
115
- : T;
113
+ export type ResolveEffect<T> =
114
+ T extends Effect.Effect<infer S, any, any> ? S : T;
116
115
 
117
116
  /**
118
117
  * Extracts the error type from an Effect.
@@ -138,9 +137,8 @@ export type ResolveEffect<T> = T extends Effect.Effect<infer S, any, any>
138
137
  * ```
139
138
  */
140
139
  // biome-ignore lint/suspicious/noExplicitAny: Utility type needs to handle any Effect type parameters
141
- export type ExtractEffectError<T> = T extends Effect.Effect<any, infer E, any>
142
- ? E
143
- : never;
140
+ export type ExtractEffectError<T> =
141
+ T extends Effect.Effect<any, infer E, any> ? E : never;
144
142
 
145
143
  /**
146
144
  * Extracts the requirements (context) type from an Effect.
@@ -10,10 +10,7 @@
10
10
 
11
11
  import { render } from "micromustache";
12
12
  import type { UploadFile } from "../../types/upload-file";
13
- import type {
14
- FileNamingConfig,
15
- NamingContext,
16
- } from "../types/flow-types";
13
+ import type { FileNamingConfig, NamingContext } from "../types/flow-types";
17
14
 
18
15
  /**
19
16
  * Extracts the base name (without extension) from a filename.
@@ -292,16 +289,44 @@ export function validatePattern(pattern: string): {
292
289
  * List of available template variables for documentation and UI.
293
290
  */
294
291
  export const AVAILABLE_TEMPLATE_VARIABLES = [
295
- { name: "baseName", description: "Filename without extension", example: "photo" },
296
- { name: "extension", description: "File extension without dot", example: "jpg" },
297
- { name: "fileName", description: "Full original filename", example: "photo.jpg" },
298
- { name: "nodeType", description: "Type of processing node", example: "resize" },
299
- { name: "nodeId", description: "Specific node instance ID", example: "resize-1" },
292
+ {
293
+ name: "baseName",
294
+ description: "Filename without extension",
295
+ example: "photo",
296
+ },
297
+ {
298
+ name: "extension",
299
+ description: "File extension without dot",
300
+ example: "jpg",
301
+ },
302
+ {
303
+ name: "fileName",
304
+ description: "Full original filename",
305
+ example: "photo.jpg",
306
+ },
307
+ {
308
+ name: "nodeType",
309
+ description: "Type of processing node",
310
+ example: "resize",
311
+ },
312
+ {
313
+ name: "nodeId",
314
+ description: "Specific node instance ID",
315
+ example: "resize-1",
316
+ },
300
317
  { name: "flowId", description: "Flow identifier", example: "flow-abc" },
301
318
  { name: "jobId", description: "Execution job ID", example: "job-123" },
302
- { name: "timestamp", description: "ISO 8601 processing time", example: "2024-01-15T10:30:00Z" },
319
+ {
320
+ name: "timestamp",
321
+ description: "ISO 8601 processing time",
322
+ example: "2024-01-15T10:30:00Z",
323
+ },
303
324
  { name: "width", description: "Output width (image/video)", example: "800" },
304
- { name: "height", description: "Output height (image/video)", example: "600" },
325
+ {
326
+ name: "height",
327
+ description: "Output height (image/video)",
328
+ example: "600",
329
+ },
305
330
  { name: "format", description: "Output format", example: "webp" },
306
331
  { name: "quality", description: "Quality setting", example: "80" },
307
332
  { name: "pageNumber", description: "Page number (documents)", example: "1" },
@@ -8,6 +8,13 @@ import {
8
8
  } from "../types/data-store";
9
9
  import { UploadEngine } from "../upload";
10
10
 
11
+ /**
12
+ * EICAR test file signature (standard antivirus test file)
13
+ * This is a safe, non-malicious string used to test antivirus software
14
+ */
15
+ const EICAR_SIGNATURE =
16
+ "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
17
+
11
18
  /**
12
19
  * Mock UploadEngine implementation for testing.
13
20
  *
@@ -30,7 +37,17 @@ export const TestUploadEngine = Layer.succeed(
30
37
  UploadEngine.of({
31
38
  read: (fileId: string, _clientId: string | null) =>
32
39
  Effect.sync(() => {
33
- // Generate mock file data based on fileId
40
+ // Return infected content for files that should trigger virus detection
41
+ // This allows tests to verify virus scanning behavior
42
+ if (
43
+ fileId.toLowerCase().includes("infected") ||
44
+ fileId.toLowerCase().includes("virus") ||
45
+ fileId.toLowerCase().includes("malware") ||
46
+ fileId.toLowerCase().includes("eicar")
47
+ ) {
48
+ return new TextEncoder().encode(EICAR_SIGNATURE);
49
+ }
50
+ // Generate clean mock file data for other files
34
51
  const text = `Content of file ${fileId}`;
35
52
  return new TextEncoder().encode(text);
36
53
  }),
@@ -8,8 +8,8 @@
8
8
  * @module types/circuit-breaker-store
9
9
  */
10
10
 
11
- import { Context, Effect, Layer } from "effect";
12
- import { UploadistaError } from "../errors";
11
+ import { Context, type Effect, Layer } from "effect";
12
+ import type { UploadistaError } from "../errors";
13
13
 
14
14
  // ============================================================================
15
15
  // State Types
@@ -279,7 +279,10 @@ export type DataStore<TData = unknown> = {
279
279
  readonly readStream?: (
280
280
  file_id: string,
281
281
  config?: StreamingConfig,
282
- ) => Effect.Effect<Stream.Stream<Uint8Array, UploadistaError>, UploadistaError>;
282
+ ) => Effect.Effect<
283
+ Stream.Stream<Uint8Array, UploadistaError>,
284
+ UploadistaError
285
+ >;
283
286
  readonly write: (
284
287
  options: DataStoreWriteOptions,
285
288
  dependencies: {
@@ -196,15 +196,17 @@ export class TypedKvStore<TData> implements KvStore<TData> {
196
196
  list = (): Effect.Effect<Array<string>, UploadistaError> => {
197
197
  if (this.baseStore.list) {
198
198
  // Get keys with prefix and strip the prefix for use with get/set/delete
199
- return this.baseStore.list(this.keyPrefix).pipe(
200
- Effect.map((keys) =>
201
- keys.map((key) =>
202
- key.startsWith(this.keyPrefix)
203
- ? key.slice(this.keyPrefix.length)
204
- : key,
199
+ return this.baseStore
200
+ .list(this.keyPrefix)
201
+ .pipe(
202
+ Effect.map((keys) =>
203
+ keys.map((key) =>
204
+ key.startsWith(this.keyPrefix)
205
+ ? key.slice(this.keyPrefix.length)
206
+ : key,
207
+ ),
205
208
  ),
206
- ),
207
- );
209
+ );
208
210
  }
209
211
  return Effect.fail(
210
212
  new UploadistaError({
@@ -419,10 +421,9 @@ export const flowJobKvStore = Layer.effect(
419
421
  * });
420
422
  * ```
421
423
  */
422
- export class DeadLetterQueueKVStore extends Context.Tag("DeadLetterQueueKVStore")<
423
- DeadLetterQueueKVStore,
424
- KvStore<DeadLetterItem>
425
- >() {}
424
+ export class DeadLetterQueueKVStore extends Context.Tag(
425
+ "DeadLetterQueueKVStore",
426
+ )<DeadLetterQueueKVStore, KvStore<DeadLetterItem>>() {}
426
427
 
427
428
  /**
428
429
  * Effect Layer that creates the DeadLetterQueueKVStore from a BaseKvStore.
@@ -17,13 +17,38 @@ export const traceContextSchema = z.object({
17
17
  traceFlags: z.number(),
18
18
  });
19
19
 
20
+ /**
21
+ * JSON value type that allows any JSON-serializable data.
22
+ * Used for metadata values which can be primitives, arrays, or nested objects.
23
+ */
24
+ export type JsonValue =
25
+ | string
26
+ | number
27
+ | boolean
28
+ | null
29
+ | JsonValue[]
30
+ | { [key: string]: JsonValue };
31
+
32
+ /**
33
+ * JSON value schema that allows any JSON-serializable data.
34
+ * This is used for metadata values which can be primitives, arrays, or objects.
35
+ */
36
+ const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>
37
+ z.union([
38
+ z.string(),
39
+ z.number(),
40
+ z.boolean(),
41
+ z.null(),
42
+ z.array(jsonValueSchema),
43
+ z.record(z.string(), jsonValueSchema),
44
+ ]),
45
+ );
46
+
20
47
  export const uploadFileSchema = z.object({
21
48
  id: z.string(),
22
49
  size: z.number().optional(),
23
50
  offset: z.number(),
24
- metadata: z
25
- .record(z.string(), z.union([z.string(), z.number(), z.boolean()]))
26
- .optional(),
51
+ metadata: z.record(z.string(), jsonValueSchema).optional(),
27
52
  creationDate: z.string().optional(),
28
53
  url: z.string().optional(),
29
54
  sizeIsDeferred: z.boolean().optional(),
@@ -172,7 +197,7 @@ export type UploadFile = {
172
197
  jobId: string;
173
198
  };
174
199
  size?: number | undefined;
175
- metadata?: Record<string, string | number | boolean> | undefined;
200
+ metadata?: Record<string, JsonValue> | undefined;
176
201
  creationDate?: string | undefined;
177
202
  url?: string | undefined;
178
203
  sizeIsDeferred?: boolean | undefined;