@discordkit/core 3.2.0 → 4.0.1

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 (247) hide show
  1. package/CHANGELOG.md +423 -0
  2. package/README.md +52 -0
  3. package/dist/index.d.mts +23 -0
  4. package/dist/index.mjs +23 -0
  5. package/dist/requests/DiscordSession.d.mts +72 -0
  6. package/dist/requests/DiscordSession.d.mts.map +1 -0
  7. package/dist/requests/DiscordSession.mjs +262 -0
  8. package/dist/requests/DiscordSession.mjs.map +1 -0
  9. package/dist/requests/addParams.d.mts +16 -0
  10. package/dist/requests/addParams.d.mts.map +1 -0
  11. package/dist/requests/addParams.mjs +26 -0
  12. package/dist/requests/addParams.mjs.map +1 -0
  13. package/dist/requests/buildURL.d.mts +8 -0
  14. package/dist/requests/buildURL.d.mts.map +1 -0
  15. package/dist/requests/buildURL.mjs +9 -0
  16. package/dist/requests/buildURL.mjs.map +1 -0
  17. package/dist/requests/getAsset.d.mts +8 -0
  18. package/dist/requests/getAsset.d.mts.map +1 -0
  19. package/dist/requests/getAsset.mjs +8 -0
  20. package/dist/requests/getAsset.mjs.map +1 -0
  21. package/dist/requests/index.d.mts +9 -0
  22. package/dist/requests/index.mjs +9 -0
  23. package/dist/requests/methods.d.mts +64 -0
  24. package/dist/requests/methods.d.mts.map +1 -0
  25. package/dist/requests/methods.mjs +12 -0
  26. package/dist/requests/methods.mjs.map +1 -0
  27. package/dist/requests/request.d.mts +28 -0
  28. package/dist/requests/request.d.mts.map +1 -0
  29. package/dist/requests/request.mjs +31 -0
  30. package/dist/requests/request.mjs.map +1 -0
  31. package/dist/requests/toProcedure.d.mts +41 -0
  32. package/dist/requests/toProcedure.d.mts.map +1 -0
  33. package/dist/requests/toProcedure.mjs +29 -0
  34. package/dist/requests/toProcedure.mjs.map +1 -0
  35. package/dist/requests/toQuery.d.mts +37 -0
  36. package/dist/requests/toQuery.d.mts.map +1 -0
  37. package/dist/requests/toQuery.mjs +10 -0
  38. package/dist/requests/toQuery.mjs.map +1 -0
  39. package/dist/requests/toValidated.d.mts +17 -0
  40. package/dist/requests/toValidated.d.mts.map +1 -0
  41. package/dist/requests/toValidated.mjs +27 -0
  42. package/dist/requests/toValidated.mjs.map +1 -0
  43. package/dist/requests/{verifyKey.d.ts → verifyKey.d.mts} +5 -1
  44. package/dist/requests/verifyKey.d.mts.map +1 -0
  45. package/dist/requests/verifyKey.mjs +64 -0
  46. package/dist/requests/verifyKey.mjs.map +1 -0
  47. package/dist/utils/isBetween.d.mts +5 -0
  48. package/dist/utils/isBetween.d.mts.map +1 -0
  49. package/dist/utils/isBetween.mjs +6 -0
  50. package/dist/utils/isBetween.mjs.map +1 -0
  51. package/dist/utils/{isNonNullable.js → isNonNullable.d.mts} +6 -2
  52. package/dist/utils/isNonNullable.d.mts.map +1 -0
  53. package/dist/utils/isNonNullable.mjs +24 -0
  54. package/dist/utils/isNonNullable.mjs.map +1 -0
  55. package/dist/utils/isNumericString.d.mts +5 -0
  56. package/dist/utils/isNumericString.d.mts.map +1 -0
  57. package/dist/utils/isNumericString.mjs +6 -0
  58. package/dist/utils/isNumericString.mjs.map +1 -0
  59. package/dist/utils/isObject.d.mts +5 -0
  60. package/dist/utils/isObject.d.mts.map +1 -0
  61. package/dist/utils/isObject.mjs +6 -0
  62. package/dist/utils/isObject.mjs.map +1 -0
  63. package/dist/utils/sleep.d.mts +8 -0
  64. package/dist/utils/sleep.d.mts.map +1 -0
  65. package/dist/utils/sleep.mjs +9 -0
  66. package/dist/utils/sleep.mjs.map +1 -0
  67. package/dist/utils/toCamelCase.d.mts +5 -0
  68. package/dist/utils/toCamelCase.d.mts.map +1 -0
  69. package/dist/utils/toCamelCase.mjs +6 -0
  70. package/dist/utils/toCamelCase.mjs.map +1 -0
  71. package/dist/utils/toCamelKeys.d.mts +20 -0
  72. package/dist/utils/toCamelKeys.d.mts.map +1 -0
  73. package/dist/utils/toCamelKeys.mjs +15 -0
  74. package/dist/utils/toCamelKeys.mjs.map +1 -0
  75. package/dist/utils/toSnakeCase.d.mts +5 -0
  76. package/dist/utils/toSnakeCase.d.mts.map +1 -0
  77. package/dist/utils/toSnakeCase.mjs +6 -0
  78. package/dist/utils/toSnakeCase.mjs.map +1 -0
  79. package/dist/utils/toSnakeKeys.d.mts +24 -0
  80. package/dist/utils/toSnakeKeys.d.mts.map +1 -0
  81. package/dist/utils/toSnakeKeys.mjs +15 -0
  82. package/dist/utils/toSnakeKeys.mjs.map +1 -0
  83. package/dist/validations/asDigits.d.mts +13 -0
  84. package/dist/validations/asDigits.d.mts.map +1 -0
  85. package/dist/validations/asDigits.mjs +12 -0
  86. package/dist/validations/asDigits.mjs.map +1 -0
  87. package/dist/validations/asInteger.d.mts +13 -0
  88. package/dist/validations/asInteger.d.mts.map +1 -0
  89. package/dist/validations/asInteger.mjs +12 -0
  90. package/dist/validations/asInteger.mjs.map +1 -0
  91. package/dist/validations/bitfield.d.mts +24 -0
  92. package/dist/validations/bitfield.d.mts.map +1 -0
  93. package/dist/validations/bitfield.mjs +22 -0
  94. package/dist/validations/bitfield.mjs.map +1 -0
  95. package/dist/validations/boundedArray.d.mts +14 -0
  96. package/dist/validations/boundedArray.d.mts.map +1 -0
  97. package/dist/validations/boundedArray.mjs +11 -0
  98. package/dist/validations/boundedArray.mjs.map +1 -0
  99. package/dist/validations/boundedInteger.d.mts +14 -0
  100. package/dist/validations/boundedInteger.d.mts.map +1 -0
  101. package/dist/validations/boundedInteger.mjs +11 -0
  102. package/dist/validations/boundedInteger.mjs.map +1 -0
  103. package/dist/validations/boundedString.d.mts +15 -0
  104. package/dist/validations/boundedString.d.mts.map +1 -0
  105. package/dist/validations/boundedString.mjs +12 -0
  106. package/dist/validations/boundedString.mjs.map +1 -0
  107. package/dist/validations/datauri.d.mts +25 -0
  108. package/dist/validations/datauri.d.mts.map +1 -0
  109. package/dist/validations/datauri.mjs +19 -0
  110. package/dist/validations/datauri.mjs.map +1 -0
  111. package/dist/validations/fileUpload.d.mts +130 -0
  112. package/dist/validations/fileUpload.d.mts.map +1 -0
  113. package/dist/validations/fileUpload.mjs +116 -0
  114. package/dist/validations/fileUpload.mjs.map +1 -0
  115. package/dist/validations/hasMimeType.d.mts +17 -0
  116. package/dist/validations/hasMimeType.d.mts.map +1 -0
  117. package/dist/validations/hasMimeType.mjs +18 -0
  118. package/dist/validations/hasMimeType.mjs.map +1 -0
  119. package/dist/validations/hasSize.d.mts +11 -0
  120. package/dist/validations/hasSize.d.mts.map +1 -0
  121. package/dist/validations/hasSize.mjs +14 -0
  122. package/dist/validations/hasSize.mjs.map +1 -0
  123. package/dist/validations/index.d.mts +15 -0
  124. package/dist/validations/index.mjs +15 -0
  125. package/dist/validations/schema.d.mts +103 -0
  126. package/dist/validations/schema.d.mts.map +1 -0
  127. package/dist/validations/schema.mjs +111 -0
  128. package/dist/validations/schema.mjs.map +1 -0
  129. package/dist/validations/{snowflake.d.ts → snowflake.d.mts} +10 -7
  130. package/dist/validations/snowflake.d.mts.map +1 -0
  131. package/dist/validations/snowflake.mjs +30 -0
  132. package/dist/validations/snowflake.mjs.map +1 -0
  133. package/dist/validations/timestamp.d.mts +8 -0
  134. package/dist/validations/timestamp.d.mts.map +1 -0
  135. package/dist/validations/timestamp.mjs +8 -0
  136. package/dist/validations/timestamp.mjs.map +1 -0
  137. package/dist/validations/toBlob.d.mts +8 -0
  138. package/dist/validations/toBlob.d.mts.map +1 -0
  139. package/dist/validations/toBlob.mjs +19 -0
  140. package/dist/validations/toBlob.mjs.map +1 -0
  141. package/dist/validations/url.d.mts +7 -0
  142. package/dist/validations/url.d.mts.map +1 -0
  143. package/dist/validations/url.mjs +7 -0
  144. package/dist/validations/url.mjs.map +1 -0
  145. package/package.json +10 -23
  146. package/dist/index.d.ts +0 -2
  147. package/dist/index.js +0 -3
  148. package/dist/index.js.map +0 -1
  149. package/dist/requests/DiscordSession.d.ts +0 -25
  150. package/dist/requests/DiscordSession.js +0 -255
  151. package/dist/requests/DiscordSession.js.map +0 -1
  152. package/dist/requests/addParams.d.ts +0 -2
  153. package/dist/requests/addParams.js +0 -11
  154. package/dist/requests/addParams.js.map +0 -1
  155. package/dist/requests/buildURL.d.ts +0 -2
  156. package/dist/requests/buildURL.js +0 -4
  157. package/dist/requests/buildURL.js.map +0 -1
  158. package/dist/requests/getAsset.d.ts +0 -2
  159. package/dist/requests/getAsset.js +0 -3
  160. package/dist/requests/getAsset.js.map +0 -1
  161. package/dist/requests/index.d.ts +0 -8
  162. package/dist/requests/index.js +0 -9
  163. package/dist/requests/index.js.map +0 -1
  164. package/dist/requests/methods.d.ts +0 -13
  165. package/dist/requests/methods.js +0 -8
  166. package/dist/requests/methods.js.map +0 -1
  167. package/dist/requests/request.d.ts +0 -2
  168. package/dist/requests/request.js +0 -30
  169. package/dist/requests/request.js.map +0 -1
  170. package/dist/requests/toProcedure.d.ts +0 -31
  171. package/dist/requests/toProcedure.js +0 -36
  172. package/dist/requests/toProcedure.js.map +0 -1
  173. package/dist/requests/toQuery.d.ts +0 -28
  174. package/dist/requests/toQuery.js +0 -9
  175. package/dist/requests/toQuery.js.map +0 -1
  176. package/dist/requests/toValidated.d.ts +0 -13
  177. package/dist/requests/toValidated.js +0 -29
  178. package/dist/requests/toValidated.js.map +0 -1
  179. package/dist/requests/verifyKey.js +0 -91
  180. package/dist/requests/verifyKey.js.map +0 -1
  181. package/dist/utils/isBetween.d.ts +0 -1
  182. package/dist/utils/isBetween.js +0 -2
  183. package/dist/utils/isBetween.js.map +0 -1
  184. package/dist/utils/isNonNullable.d.ts +0 -20
  185. package/dist/utils/isNonNullable.js.map +0 -1
  186. package/dist/utils/isNumericString.d.ts +0 -1
  187. package/dist/utils/isNumericString.js +0 -2
  188. package/dist/utils/isNumericString.js.map +0 -1
  189. package/dist/utils/isObject.d.ts +0 -1
  190. package/dist/utils/isObject.js +0 -2
  191. package/dist/utils/isObject.js.map +0 -1
  192. package/dist/utils/sleep.d.ts +0 -4
  193. package/dist/utils/sleep.js +0 -5
  194. package/dist/utils/sleep.js.map +0 -1
  195. package/dist/utils/toCamelCase.d.ts +0 -1
  196. package/dist/utils/toCamelCase.js +0 -2
  197. package/dist/utils/toCamelCase.js.map +0 -1
  198. package/dist/utils/toCamelKeys.d.ts +0 -2
  199. package/dist/utils/toCamelKeys.js +0 -16
  200. package/dist/utils/toCamelKeys.js.map +0 -1
  201. package/dist/utils/toSnakeCase.d.ts +0 -1
  202. package/dist/utils/toSnakeCase.js +0 -4
  203. package/dist/utils/toSnakeCase.js.map +0 -1
  204. package/dist/utils/toSnakeKeys.d.ts +0 -2
  205. package/dist/utils/toSnakeKeys.js +0 -16
  206. package/dist/utils/toSnakeKeys.js.map +0 -1
  207. package/dist/validations/asDigits.d.ts +0 -6
  208. package/dist/validations/asDigits.js +0 -6
  209. package/dist/validations/asDigits.js.map +0 -1
  210. package/dist/validations/asInteger.d.ts +0 -6
  211. package/dist/validations/asInteger.js +0 -6
  212. package/dist/validations/asInteger.js.map +0 -1
  213. package/dist/validations/bitfield.d.ts +0 -17
  214. package/dist/validations/bitfield.js +0 -37
  215. package/dist/validations/bitfield.js.map +0 -1
  216. package/dist/validations/boundedArray.d.ts +0 -6
  217. package/dist/validations/boundedArray.js +0 -8
  218. package/dist/validations/boundedArray.js.map +0 -1
  219. package/dist/validations/boundedInteger.d.ts +0 -6
  220. package/dist/validations/boundedInteger.js +0 -8
  221. package/dist/validations/boundedInteger.js.map +0 -1
  222. package/dist/validations/boundedString.d.ts +0 -6
  223. package/dist/validations/boundedString.js +0 -8
  224. package/dist/validations/boundedString.js.map +0 -1
  225. package/dist/validations/datauri.d.ts +0 -20
  226. package/dist/validations/datauri.js +0 -20
  227. package/dist/validations/datauri.js.map +0 -1
  228. package/dist/validations/hasMimeType.d.ts +0 -10
  229. package/dist/validations/hasMimeType.js +0 -18
  230. package/dist/validations/hasMimeType.js.map +0 -1
  231. package/dist/validations/hasSize.d.ts +0 -5
  232. package/dist/validations/hasSize.js +0 -13
  233. package/dist/validations/hasSize.js.map +0 -1
  234. package/dist/validations/index.d.ts +0 -12
  235. package/dist/validations/index.js +0 -13
  236. package/dist/validations/index.js.map +0 -1
  237. package/dist/validations/snowflake.js +0 -39
  238. package/dist/validations/snowflake.js.map +0 -1
  239. package/dist/validations/timestamp.d.ts +0 -3
  240. package/dist/validations/timestamp.js +0 -4
  241. package/dist/validations/timestamp.js.map +0 -1
  242. package/dist/validations/toBlob.d.ts +0 -4
  243. package/dist/validations/toBlob.js +0 -19
  244. package/dist/validations/toBlob.js.map +0 -1
  245. package/dist/validations/url.d.ts +0 -2
  246. package/dist/validations/url.js +0 -3
  247. package/dist/validations/url.js.map +0 -1
@@ -0,0 +1,13 @@
1
+ import { bitfield } from "./bitfield.mjs";
2
+ import * as v from "valibot";
3
+
4
+ //#region src/validations/asDigits.d.ts
5
+ /**
6
+ * Transforms a `bitfield` schema into a numeric string
7
+ *
8
+ * @__NO_SIDE_EFFECTS__
9
+ */
10
+ declare const asDigits: (schema: ReturnType<typeof bitfield>) => v.GenericSchema<string>;
11
+ //#endregion
12
+ export { asDigits };
13
+ //# sourceMappingURL=asDigits.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asDigits.d.mts","names":[],"sources":["../../src/validations/asDigits.ts"],"mappings":";;;;;;AAQA;;;cAAa,QAAA,GACX,MAAA,EAAQ,UAAA,QAAkB,QAAA,MACzB,CAAA,CAAE,aAAA"}
@@ -0,0 +1,12 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/asDigits.ts
3
+ /**
4
+ * Transforms a `bitfield` schema into a numeric string
5
+ *
6
+ * @__NO_SIDE_EFFECTS__
7
+ */
8
+ const asDigits = (schema) => v.pipe(schema, v.transform((val) => val.toString()), v.digits());
9
+ //#endregion
10
+ export { asDigits };
11
+
12
+ //# sourceMappingURL=asDigits.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asDigits.mjs","names":[],"sources":["../../src/validations/asDigits.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport type { bitfield } from \"./bitfield.js\";\n\n/**\n * Transforms a `bitfield` schema into a numeric string\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const asDigits = (\n schema: ReturnType<typeof bitfield>\n): v.GenericSchema<string> =>\n v.pipe(\n schema,\n v.transform((val) => val.toString()),\n v.digits()\n ) as v.GenericSchema<string>;\n"],"mappings":";;;;;;;AAQA,MAAa,YACX,WAEA,EAAE,KACA,QACA,EAAE,WAAW,QAAQ,IAAI,SAAS,CAAC,GACnC,EAAE,OAAO,CACX"}
@@ -0,0 +1,13 @@
1
+ import { bitfield } from "./bitfield.mjs";
2
+ import * as v from "valibot";
3
+
4
+ //#region src/validations/asInteger.d.ts
5
+ /**
6
+ * Transforms a `bitfield` schema into an integer
7
+ *
8
+ * @__NO_SIDE_EFFECTS__
9
+ */
10
+ declare const asInteger: (schema: ReturnType<typeof bitfield>) => v.GenericSchema<number>;
11
+ //#endregion
12
+ export { asInteger };
13
+ //# sourceMappingURL=asInteger.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asInteger.d.mts","names":[],"sources":["../../src/validations/asInteger.ts"],"mappings":";;;;;;AAQA;;;cAAa,SAAA,GACX,MAAA,EAAQ,UAAA,QAAkB,QAAA,MACzB,CAAA,CAAE,aAAA"}
@@ -0,0 +1,12 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/asInteger.ts
3
+ /**
4
+ * Transforms a `bitfield` schema into an integer
5
+ *
6
+ * @__NO_SIDE_EFFECTS__
7
+ */
8
+ const asInteger = (schema) => v.pipe(schema, v.transform((val) => parseInt(val.toString(), 10)), v.integer());
9
+ //#endregion
10
+ export { asInteger };
11
+
12
+ //# sourceMappingURL=asInteger.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asInteger.mjs","names":[],"sources":["../../src/validations/asInteger.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport type { bitfield } from \"./bitfield.js\";\n\n/**\n * Transforms a `bitfield` schema into an integer\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const asInteger = (\n schema: ReturnType<typeof bitfield>\n): v.GenericSchema<number> =>\n v.pipe(\n schema,\n v.transform((val) => parseInt(val.toString(), 10)),\n v.integer()\n ) as v.GenericSchema<number>;\n"],"mappings":";;;;;;;AAQA,MAAa,aACX,WAEA,EAAE,KACA,QACA,EAAE,WAAW,QAAQ,SAAS,IAAI,SAAS,GAAG,EAAE,CAAC,GACjD,EAAE,QAAQ,CACZ"}
@@ -0,0 +1,24 @@
1
+ import { CustomSchema, SchemaWithPipe, TitleAction } from "valibot";
2
+
3
+ //#region src/validations/bitfield.d.ts
4
+ interface Flags {
5
+ [key: string]: number | bigint | string;
6
+ }
7
+ /**
8
+ * Given an enum of bitwise flags, creates a new schema that
9
+ * can validate a [bitfield](https://en.wikipedia.org/wiki/Bit_field)
10
+ * numeric value (a data structure for efficiently serializing a
11
+ * group of boolean values).
12
+ *
13
+ * @__NO_SIDE_EFFECTS__
14
+ */
15
+ declare const bitfield: <TName extends string>(/** A name to differentiate this custom schema */
16
+
17
+ name: TName, /** An enum of bitwise flags */
18
+
19
+ flags: Flags, /** An optional error message to display in the event an invalid value is parsed */
20
+
21
+ message?: string) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TitleAction<string | number | bigint, TName>]>;
22
+ //#endregion
23
+ export { Flags, bitfield };
24
+ //# sourceMappingURL=bitfield.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitfield.d.mts","names":[],"sources":["../../src/validations/bitfield.ts"],"mappings":";;;UAWiB,KAAA;EAAA,CACd,GAAW;AAAA;;;;AAAA;AAWd;;;;cAAa,QAAA;;AAEX,IAAA,EAAM,KAAA;;AAEN,KAAA,EAAO,KAAA;;AAEP,OAAA,cACC,cAAA,WAEC,YAAA,oCACA,WAAA,2BAAsC,KAAA"}
@@ -0,0 +1,22 @@
1
+ import { isNonNullable } from "../utils/isNonNullable.mjs";
2
+ import { isNumericString } from "../utils/isNumericString.mjs";
3
+ import { custom, pipe, title } from "valibot";
4
+ //#region src/validations/bitfield.ts
5
+ /**
6
+ * Given an enum of bitwise flags, creates a new schema that
7
+ * can validate a [bitfield](https://en.wikipedia.org/wiki/Bit_field)
8
+ * numeric value (a data structure for efficiently serializing a
9
+ * group of boolean values).
10
+ *
11
+ * @__NO_SIDE_EFFECTS__
12
+ */
13
+ const bitfield = (name, flags, message = `Invalid Bitfield`) => {
14
+ const flagValues = Object.values(flags).filter((flag) => !isNaN(Number(flag)));
15
+ if (!flagValues.every((flag) => typeof flag === typeof flagValues[0])) throw new Error(`Provided Flags enum must contain values of the same type`);
16
+ const mask = flagValues.reduce((total, flag) => total | BigInt(flag), 0n);
17
+ return pipe(custom((val) => isNonNullable(val) && (typeof val === `number` || typeof val === `bigint` || isNumericString(val)) ? (BigInt(val) & mask) === BigInt(val) : false, message), title(name));
18
+ };
19
+ //#endregion
20
+ export { bitfield };
21
+
22
+ //# sourceMappingURL=bitfield.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitfield.mjs","names":[],"sources":["../../src/validations/bitfield.ts"],"sourcesContent":["import {\n custom,\n pipe,\n title,\n type SchemaWithPipe,\n type TitleAction,\n type CustomSchema\n} from \"valibot\";\nimport { isNonNullable } from \"../utils/isNonNullable.js\";\nimport { isNumericString } from \"../utils/isNumericString.js\";\n\nexport interface Flags {\n [key: string]: number | bigint | string;\n}\n\n/**\n * Given an enum of bitwise flags, creates a new schema that\n * can validate a [bitfield](https://en.wikipedia.org/wiki/Bit_field)\n * numeric value (a data structure for efficiently serializing a\n * group of boolean values).\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const bitfield = <TName extends string>(\n /** A name to differentiate this custom schema */\n name: TName,\n /** An enum of bitwise flags */\n flags: Flags,\n /** An optional error message to display in the event an invalid value is parsed */\n message: string = `Invalid Bitfield`\n): SchemaWithPipe<\n readonly [\n CustomSchema<string | number | bigint, string>,\n TitleAction<string | number | bigint, TName>\n ]\n> => {\n // because enums are bidirectionally indexed, pick only the numerical values\n const flagValues = Object.values(flags).filter(\n // flag enums have numerical values, so remove all the key name strings\n (flag) => !isNaN(Number(flag))\n );\n if (!flagValues.every((flag) => typeof flag === typeof flagValues[0])) {\n throw new Error(`Provided Flags enum must contain values of the same type`);\n }\n // combine the flags to create a validation mask\n const mask = flagValues.reduce<bigint>(\n (total, flag) => total | BigInt(flag),\n 0n\n );\n return pipe(\n custom<number | bigint | string, typeof message>(\n (val) =>\n // short-circuit on null + undefined\n isNonNullable(val) &&\n // only work on supported types\n (typeof val === `number` ||\n typeof val === `bigint` ||\n isNumericString(val))\n ? // validate the value against the given flags\n (BigInt(val) & mask) === BigInt(val)\n : false,\n message\n ),\n title(name)\n );\n};\n"],"mappings":";;;;;;;;;;;;AAuBA,MAAa,YAEX,MAEA,OAEA,UAAkB,uBAMf;CAEH,MAAM,aAAa,OAAO,OAAO,KAAK,EAAE,QAErC,SAAS,CAAC,MAAM,OAAO,IAAI,CAAC,CAC/B;CACA,IAAI,CAAC,WAAW,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,EAAE,GAClE,MAAM,IAAI,MAAM,0DAA0D;CAG5E,MAAM,OAAO,WAAW,QACrB,OAAO,SAAS,QAAQ,OAAO,IAAI,GACpC,EACF;CACA,OAAO,KACL,QACG,QAEC,cAAc,GAAG,MAEhB,OAAO,QAAQ,YACd,OAAO,QAAQ,YACf,gBAAgB,GAAG,MAEhB,OAAO,GAAG,IAAI,UAAU,OAAO,GAAG,IACnC,OACN,OACF,GACA,MAAM,IAAI,CACZ;AACF"}
@@ -0,0 +1,14 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/validations/boundedArray.d.ts
4
+ /** A non-empty array with a length within the given bounds
5
+ *
6
+ * @__NO_SIDE_EFFECTS__
7
+ */
8
+ declare const boundedArray: <TItem>(items: v.GenericSchema<TItem>, req?: number | {
9
+ min?: number;
10
+ max?: number;
11
+ }) => v.GenericSchema<TItem[]>;
12
+ //#endregion
13
+ export { boundedArray };
14
+ //# sourceMappingURL=boundedArray.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedArray.d.mts","names":[],"sources":["../../src/validations/boundedArray.ts"],"mappings":";;;;;AAMA;;cAAa,YAAA,UACX,KAAA,EAAO,CAAA,CAAE,aAAA,CAAc,KAAA,GACvB,GAAA;EAAgB,GAAA;EAAc,GAAA;AAAA,MAC7B,CAAA,CAAE,aAAA,CAAc,KAAA"}
@@ -0,0 +1,11 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/boundedArray.ts
3
+ /** A non-empty array with a length within the given bounds
4
+ *
5
+ * @__NO_SIDE_EFFECTS__
6
+ */
7
+ const boundedArray = (items, req = {}) => v.message(typeof req === `number` ? v.pipe(v.array(items), v.length(req)) : typeof req.max === `number` ? v.pipe(v.array(items), v.minLength(req.min ?? 1), v.maxLength(req.max)) : v.pipe(v.array(items), v.minLength(req.min ?? 1)), (issue) => `Expected an array with a legnth ${typeof req === `number` ? req : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has length: ${issue.received.length}`);
8
+ //#endregion
9
+ export { boundedArray };
10
+
11
+ //# sourceMappingURL=boundedArray.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedArray.mjs","names":[],"sources":["../../src/validations/boundedArray.ts"],"sourcesContent":["import * as v from \"valibot\";\n\n/** A non-empty array with a length within the given bounds\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const boundedArray = <TItem>(\n items: v.GenericSchema<TItem>,\n req: number | { min?: number; max?: number } = {}\n): v.GenericSchema<TItem[]> =>\n v.message<v.GenericSchema<TItem[]>>(\n typeof req === `number`\n ? v.pipe(v.array(items), v.length(req))\n : typeof req.max === `number`\n ? v.pipe(\n v.array(items),\n v.minLength(req.min ?? 1),\n v.maxLength(req.max)\n )\n : v.pipe(v.array(items), v.minLength(req.min ?? 1)),\n (issue) =>\n `Expected an array with a legnth ${typeof req === `number` ? req : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has length: ${issue.received.length}`\n );\n"],"mappings":";;;;;;AAMA,MAAa,gBACX,OACA,MAA+C,CAAC,MAEhD,EAAE,QACA,OAAO,QAAQ,WACX,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,EAAE,OAAO,GAAG,CAAC,IACpC,OAAO,IAAI,QAAQ,WACjB,EAAE,KACA,EAAE,MAAM,KAAK,GACb,EAAE,UAAU,IAAI,OAAO,CAAC,GACxB,EAAE,UAAU,IAAI,GAAG,CACrB,IACA,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,EAAE,UAAU,IAAI,OAAO,CAAC,CAAC,IACrD,UACC,mCAAmC,OAAO,QAAQ,WAAW,MAAM,MAAM,IAAI,OAAO,IAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,KAAK,yBAAyB,MAAM,SAAS,QACxK"}
@@ -0,0 +1,14 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/validations/boundedInteger.d.ts
4
+ /** An integer with a value within the given bounds
5
+ *
6
+ * @__NO_SIDE_EFFECTS__
7
+ */
8
+ declare const boundedInteger: (req?: number | {
9
+ min?: number;
10
+ max?: number;
11
+ }) => v.GenericSchema<number>;
12
+ //#endregion
13
+ export { boundedInteger };
14
+ //# sourceMappingURL=boundedInteger.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedInteger.d.mts","names":[],"sources":["../../src/validations/boundedInteger.ts"],"mappings":";;;;;AAMA;;cAAa,cAAA,GACX,GAAA;EAAgB,GAAA;EAAc,GAAA;AAAA,MAC7B,CAAA,CAAE,aAAa"}
@@ -0,0 +1,11 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/boundedInteger.ts
3
+ /** An integer with a value within the given bounds
4
+ *
5
+ * @__NO_SIDE_EFFECTS__
6
+ */
7
+ const boundedInteger = (req = {}) => v.message(typeof req === `number` ? v.pipe(v.number(), v.integer(), v.value(req)) : typeof req.max === `number` ? v.pipe(v.number(), v.integer(), v.minValue(req.min ?? 0), v.maxValue(req.max)) : v.pipe(v.number(), v.integer(), v.minValue(req.min ?? 0)), (issue) => `Expected an integer with a value ${typeof req === `number` ? `of ${req}` : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has value: ${issue.received.length}`);
8
+ //#endregion
9
+ export { boundedInteger };
10
+
11
+ //# sourceMappingURL=boundedInteger.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedInteger.mjs","names":[],"sources":["../../src/validations/boundedInteger.ts"],"sourcesContent":["import * as v from \"valibot\";\n\n/** An integer with a value within the given bounds\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const boundedInteger = (\n req: number | { min?: number; max?: number } = {}\n): v.GenericSchema<number> =>\n v.message<v.GenericSchema<number>>(\n typeof req === `number`\n ? v.pipe(v.number(), v.integer(), v.value(req))\n : typeof req.max === `number`\n ? v.pipe(\n v.number(),\n v.integer(),\n v.minValue(req.min ?? 0),\n v.maxValue(req.max)\n )\n : v.pipe(v.number(), v.integer(), v.minValue(req.min ?? 0)),\n (issue) =>\n `Expected an integer with a value ${typeof req === `number` ? `of ${req}` : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has value: ${issue.received.length}`\n );\n"],"mappings":";;;;;;AAMA,MAAa,kBACX,MAA+C,CAAC,MAEhD,EAAE,QACA,OAAO,QAAQ,WACX,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,MAAM,GAAG,CAAC,IAC5C,OAAO,IAAI,QAAQ,WACjB,EAAE,KACA,EAAE,OAAO,GACT,EAAE,QAAQ,GACV,EAAE,SAAS,IAAI,OAAO,CAAC,GACvB,EAAE,SAAS,IAAI,GAAG,CACpB,IACA,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,SAAS,IAAI,OAAO,CAAC,CAAC,IAC7D,UACC,oCAAoC,OAAO,QAAQ,WAAW,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,KAAK,wBAAwB,MAAM,SAAS,QAChL"}
@@ -0,0 +1,15 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/validations/boundedString.d.ts
4
+ /**
5
+ * A non-empty string with a length within the given bounds.
6
+ *
7
+ * @__NO_SIDE_EFFECTS__
8
+ */
9
+ declare const boundedString: (req?: number | {
10
+ min?: number;
11
+ max?: number;
12
+ }) => v.GenericSchema<string>;
13
+ //#endregion
14
+ export { boundedString };
15
+ //# sourceMappingURL=boundedString.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedString.d.mts","names":[],"sources":["../../src/validations/boundedString.ts"],"mappings":";;;;;AAOA;;;cAAa,aAAA,GACX,GAAA;EAAgB,GAAA;EAAc,GAAA;AAAA,MAC7B,CAAA,CAAE,aAAa"}
@@ -0,0 +1,12 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/boundedString.ts
3
+ /**
4
+ * A non-empty string with a length within the given bounds.
5
+ *
6
+ * @__NO_SIDE_EFFECTS__
7
+ */
8
+ const boundedString = (req = {}) => v.message(typeof req === `number` ? v.pipe(v.string(), v.length(req)) : typeof req.max === `number` ? v.pipe(v.string(), v.minLength(req.min ?? 1), v.maxLength(req.max)) : v.pipe(v.string(), v.minLength(req.min ?? 1)), (issue) => `Expected a string with a legnth ${typeof req === `number` ? req : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has length: ${issue.received.length}`);
9
+ //#endregion
10
+ export { boundedString };
11
+
12
+ //# sourceMappingURL=boundedString.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedString.mjs","names":[],"sources":["../../src/validations/boundedString.ts"],"sourcesContent":["import * as v from \"valibot\";\n\n/**\n * A non-empty string with a length within the given bounds.\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const boundedString = (\n req: number | { min?: number; max?: number } = {}\n): v.GenericSchema<string> =>\n v.message<v.GenericSchema<string>>(\n typeof req === `number`\n ? v.pipe(v.string(), v.length(req))\n : typeof req.max === `number`\n ? v.pipe(v.string(), v.minLength(req.min ?? 1), v.maxLength(req.max))\n : v.pipe(v.string(), v.minLength(req.min ?? 1)),\n (issue) =>\n `Expected a string with a legnth ${typeof req === `number` ? req : `>= ${req.min ?? 0}${req.max ? `&& <= ${req.max}` : ``}`}, received has length: ${issue.received.length}`\n );\n"],"mappings":";;;;;;;AAOA,MAAa,iBACX,MAA+C,CAAC,MAEhD,EAAE,QACA,OAAO,QAAQ,WACX,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,CAAC,IAChC,OAAO,IAAI,QAAQ,WACjB,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,UAAU,IAAI,GAAG,CAAC,IAClE,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,UAAU,IAAI,OAAO,CAAC,CAAC,IACjD,UACC,mCAAmC,OAAO,QAAQ,WAAW,MAAM,MAAM,IAAI,OAAO,IAAI,IAAI,MAAM,SAAS,IAAI,QAAQ,KAAK,yBAAyB,MAAM,SAAS,QACxK"}
@@ -0,0 +1,25 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/validations/datauri.d.ts
4
+ declare const datauriRegex: RegExp;
5
+ /**
6
+ * Extracts metadata from a given Data URI such as it's
7
+ * MIME type, params, and encoding
8
+ *
9
+ * Returns an empty object when given an invalid Data URI
10
+ */
11
+ declare const extractDataURIMetadata: (val: string) => Partial<{
12
+ mediaType: string;
13
+ mimeType: `${string}/${string}`;
14
+ params: string;
15
+ encoding: string;
16
+ data: string;
17
+ }>;
18
+ declare const toBase64: (data: string) => string;
19
+ /**
20
+ * Validates that a string is a [data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme)
21
+ */
22
+ declare const datauri: v.GenericSchema<string>;
23
+ //#endregion
24
+ export { datauri, datauriRegex, extractDataURIMetadata, toBase64 };
25
+ //# sourceMappingURL=datauri.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datauri.d.mts","names":[],"sources":["../../src/validations/datauri.ts"],"mappings":";;;cAEa,YAAA,EAAY,MACsK;;AAD/L;;;;AAC+L;cAQlL,sBAAA,GACX,GAAA,aACC,OAAO;EACR,SAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;AAAA;AAAA,cAGW,QAAA,GAAY,IAAY;;;;cAaxB,OAAA,EAAS,CAAA,CAAE,aAAa"}
@@ -0,0 +1,19 @@
1
+ import * as v from "valibot";
2
+ //#region src/validations/datauri.ts
3
+ const datauriRegex = /^data:((?<mediaType>(?<mimeType>[a-z]+\/[a-z0-9-+.]+)(?<params>;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*))?(?<encoding>;base64)?,(?<data>[a-z0-9!$&',()*+;=\-._~:@/?%\s<>]*?)$/i;
4
+ /**
5
+ * Extracts metadata from a given Data URI such as it's
6
+ * MIME type, params, and encoding
7
+ *
8
+ * Returns an empty object when given an invalid Data URI
9
+ */
10
+ const extractDataURIMetadata = (val) => datauriRegex.exec(val)?.groups ?? {};
11
+ const toBase64 = (data) => typeof Buffer !== `undefined` ? Buffer.from(data, `base64`).toString() : atob(btoa(String.fromCharCode(...new TextEncoder().encode(data))).replace(/\+/g, `-`).replace(/\//g, `_`).replace(/=/g, ``));
12
+ /**
13
+ * Validates that a string is a [data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme)
14
+ */
15
+ const datauri = v.pipe(v.custom((val) => typeof val === `string` && val.length > 0 && datauriRegex.test(val), `Invalid Data URI`), v.title(`datauri`));
16
+ //#endregion
17
+ export { datauri, datauriRegex, extractDataURIMetadata, toBase64 };
18
+
19
+ //# sourceMappingURL=datauri.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datauri.mjs","names":[],"sources":["../../src/validations/datauri.ts"],"sourcesContent":["import * as v from \"valibot\";\n\nexport const datauriRegex =\n /^data:((?<mediaType>(?<mimeType>[a-z]+\\/[a-z0-9-+.]+)(?<params>;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*))?(?<encoding>;base64)?,(?<data>[a-z0-9!$&',()*+;=\\-._~:@/?%\\s<>]*?)$/i;\n\n/**\n * Extracts metadata from a given Data URI such as it's\n * MIME type, params, and encoding\n *\n * Returns an empty object when given an invalid Data URI\n */\nexport const extractDataURIMetadata = (\n val: string\n): Partial<{\n mediaType: string;\n mimeType: `${string}/${string}`;\n params: string;\n encoding: string;\n data: string;\n}> => datauriRegex.exec(val)?.groups ?? {};\n\nexport const toBase64 = (data: string): string =>\n typeof Buffer !== `undefined`\n ? Buffer.from(data, `base64`).toString()\n : atob(\n btoa(String.fromCharCode(...new TextEncoder().encode(data)))\n .replace(/\\+/g, `-`)\n .replace(/\\//g, `_`)\n .replace(/=/g, ``)\n );\n\n/**\n * Validates that a string is a [data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme)\n */\nexport const datauri: v.GenericSchema<string> = v.pipe(\n v.custom<string>(\n (val) =>\n typeof val === `string` && val.length > 0 && datauriRegex.test(val),\n `Invalid Data URI`\n ),\n v.title(`datauri`)\n);\n"],"mappings":";;AAEA,MAAa,eACX;;;;;;;AAQF,MAAa,0BACX,QAOI,aAAa,KAAK,GAAG,GAAG,UAAU,CAAC;AAEzC,MAAa,YAAY,SACvB,OAAO,WAAW,cACd,OAAO,KAAK,MAAM,QAAQ,EAAE,SAAS,IACrC,KACE,KAAK,OAAO,aAAa,GAAG,IAAI,YAAY,EAAE,OAAO,IAAI,CAAC,CAAC,EACxD,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,MAAM,EAAE,CACrB;;;;AAKN,MAAa,UAAmC,EAAE,KAChD,EAAE,QACC,QACC,OAAO,QAAQ,YAAY,IAAI,SAAS,KAAK,aAAa,KAAK,GAAG,GACpE,kBACF,GACA,EAAE,MAAM,SAAS,CACnB"}
@@ -0,0 +1,130 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/validations/fileUpload.d.ts
4
+ /**
5
+ * The shape of a single file upload — used wherever a Discord endpoint
6
+ * accepts an attached file via `multipart/form-data`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * await executeWebhook({
11
+ * webhook: "...",
12
+ * token: "...",
13
+ * body: {
14
+ * content: "Look at this!",
15
+ * files: [
16
+ * { filename: "photo.png", content: new Blob([bytes], { type: "image/png" }) }
17
+ * ]
18
+ * }
19
+ * });
20
+ * ```
21
+ */
22
+ interface FileUpload {
23
+ /** Filename including extension. Required for the multipart `Content-Disposition` header. */
24
+ filename: string;
25
+ /** The binary content. Accepts a web-standard `Blob` or `File`. */
26
+ content: Blob;
27
+ /** Optional MIME type. If omitted, taken from the `Blob`'s `type` property. */
28
+ contentType?: string;
29
+ }
30
+ /** Type guard — true if `val` looks like a {@link FileUpload}. */
31
+ declare const isFileUpload: (val: unknown) => val is FileUpload;
32
+ /**
33
+ * Valibot schema for a single file upload. Validates the shape and
34
+ * surfaces a clean TypeScript type to consumers.
35
+ */
36
+ declare const fileUpload: v.GenericSchema<FileUpload>;
37
+ /**
38
+ * Walks a value and returns all {@link FileUpload}s within it, along
39
+ * with the path each one occupies.
40
+ */
41
+ declare const collectFileUploads: (val: unknown, path?: ReadonlyArray<string | number>) => ReadonlyArray<{
42
+ readonly path: ReadonlyArray<string | number>;
43
+ readonly file: FileUpload;
44
+ }>;
45
+ /**
46
+ * Given a body that contains one or more {@link FileUpload}s, produce
47
+ * a `FormData` payload Discord can consume.
48
+ *
49
+ * Files are appended as `files[n]` parts; the rest of the body is
50
+ * snake_cased and JSON-stringified into a `payload_json` part.
51
+ *
52
+ * Each FileUpload in the body is replaced by its attachment placeholder
53
+ * `{ id: n }` so that an `attachments` array (if present) can reference
54
+ * uploads by index. Discord matches these placeholders to the
55
+ * corresponding `files[n]` parts.
56
+ */
57
+ declare const toMultipartBody: (body: unknown, toSnakeKeys: (val: object) => unknown) => FormData;
58
+ /**
59
+ * Sentinel symbol used to mark a validated body as multipart-eligible.
60
+ * Read by the request layer at serialization time.
61
+ *
62
+ * The marker is attached as a non-enumerable property on the parsed
63
+ * body so it doesn't leak into JSON serialization or the TypeScript
64
+ * output type.
65
+ */
66
+ declare const MULTIPART_MARKER: unique symbol;
67
+ /**
68
+ * Returns true if `body` should be serialized as `multipart/form-data`.
69
+ *
70
+ * Two signals trigger multipart serialization:
71
+ *
72
+ * 1. **Schema-tagged** — the body was parsed by a {@link multipart}-wrapped
73
+ * schema and at least one {@link FileUpload} was present. The wrapper
74
+ * stamps a non-enumerable {@link MULTIPART_MARKER} on the parsed value.
75
+ * This is the fast path for the validated flow (e.g., `toValidated`).
76
+ *
77
+ * 2. **Value-detected** — the body contains a {@link FileUpload} anywhere
78
+ * in its shape, regardless of whether it was validated. This safety net
79
+ * keeps consumers who bypass validation from silently dropping their
80
+ * files into a JSON body where `Blob` would serialize as `{}`.
81
+ *
82
+ * Either signal switches the request to multipart.
83
+ */
84
+ declare const shouldSerializeAsMultipart: (body: unknown) => boolean;
85
+ /**
86
+ * Wraps an object schema to mark its body as a potential multipart payload.
87
+ *
88
+ * Use {@link multipart} instead of `v.object` whenever an endpoint's body
89
+ * may contain one or more {@link fileUpload} fields (or arrays of them,
90
+ * or optional uploads). The wrapper validates the same shape as
91
+ * `v.object(entries)`. At validation time, the wrapper inspects the
92
+ * parsed body for {@link FileUpload}s. If any are present, it stamps a
93
+ * non-enumerable {@link MULTIPART_MARKER} on the result; the request
94
+ * layer reads that marker at serialization time to choose between
95
+ * `multipart/form-data` (marker present) and `application/json`
96
+ * (marker absent).
97
+ *
98
+ * Pass `{ partial: true }` for endpoints where every field is optional —
99
+ * the wrapper applies `v.partial(...)` to the inner object before piping
100
+ * the transform. `v.partial` itself can't wrap the piped result (it only
101
+ * accepts plain object schemas), so the option lives here.
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * import { multipart, fileUpload } from "@discordkit/core";
106
+ * import * as v from "valibot";
107
+ *
108
+ * export const updateAvatarSchema = v.object({
109
+ * body: multipart({
110
+ * avatar: v.exactOptional(fileUpload),
111
+ * bio: v.exactOptional(v.string())
112
+ * })
113
+ * });
114
+ *
115
+ * // Every field optional:
116
+ * export const editMessageSchema = v.object({
117
+ * body: multipart(
118
+ * { content: v.string(), files: v.array(fileUpload) },
119
+ * { partial: true }
120
+ * )
121
+ * });
122
+ * ```
123
+ */
124
+ declare function multipart<TEntries extends v.ObjectEntries>(entries: TEntries): v.GenericSchema<v.InferOutput<v.ObjectSchema<TEntries, undefined>>>;
125
+ declare function multipart<TEntries extends v.ObjectEntries>(entries: TEntries, options: {
126
+ partial: true;
127
+ }): v.GenericSchema<v.InferOutput<v.SchemaWithPartial<v.ObjectSchema<TEntries, undefined>, undefined>>>;
128
+ //#endregion
129
+ export { FileUpload, MULTIPART_MARKER, collectFileUploads, fileUpload, isFileUpload, multipart, shouldSerializeAsMultipart, toMultipartBody };
130
+ //# sourceMappingURL=fileUpload.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUpload.d.mts","names":[],"sources":["../../src/validations/fileUpload.ts"],"mappings":";;;;;AAqBA;;;;;;;;;AAMa;AAIb;;;;;;UAViB,UAAA;EAoBhB;EAlBC,QAAA;EAwBW;EAtBX,OAAA,EAAS,IAAI;;EAEb,WAAA;AAAA;;cAIW,YAAA,GAAgB,GAAA,cAAe,GAAA,IAAO,UAUlD;;AAMkD;AASnD;;cATa,UAAA,EAAY,CAAA,CAAE,aAAa,CAAC,UAAA;;;;;cAS5B,kBAAA,GACX,GAAA,WACA,IAAA,GAAM,aAAA,sBACL,aAAA;EAAA,SACQ,IAAA,EAAM,aAAA;EAAA,SACN,IAAA,EAAM,UAAA;AAAA;;;;;;;;AAAU;AAqD3B;;;;cAAa,eAAA,GACX,IAAA,WAIA,WAAA,GAAc,GAAA,yBACb,QAiCF;;;;;AAAA;AAUD;;;cAAa,gBAAA;AAA2D;AAmBxE;;;;AAAwD;AA6CxD;;;;;;;;;;;AAhEwE,cAmB3D,0BAAA,GAA8B,IAAa;;;;;;;;;;;;;AA+CA;AACxD;;;;;;;;;;;;;;;;;;;;;;;;;;iBAHgB,SAAA,kBAA2B,CAAA,CAAE,aAAA,EAC3C,OAAA,EAAS,QAAA,GACR,CAAA,CAAE,aAAA,CAAc,CAAA,CAAE,WAAA,CAAY,CAAA,CAAE,YAAA,CAAa,QAAA;AAAA,iBAChC,SAAA,kBAA2B,CAAA,CAAE,aAAA,EAC3C,OAAA,EAAS,QAAA,EACT,OAAA;EAAW,OAAA;AAAA,IACV,CAAA,CAAE,aAAA,CACH,CAAA,CAAE,WAAA,CACA,CAAA,CAAE,iBAAA,CAAkB,CAAA,CAAE,YAAA,CAAa,QAAA"}
@@ -0,0 +1,116 @@
1
+ import { isObject } from "../utils/isObject.mjs";
2
+ import * as v from "valibot";
3
+ //#region src/validations/fileUpload.ts
4
+ /** Type guard — true if `val` looks like a {@link FileUpload}. */
5
+ const isFileUpload = (val) => {
6
+ if (!isObject(val)) return false;
7
+ const content = val.content;
8
+ return typeof val.filename === `string` && typeof content?.arrayBuffer === `function`;
9
+ };
10
+ /**
11
+ * Valibot schema for a single file upload. Validates the shape and
12
+ * surfaces a clean TypeScript type to consumers.
13
+ */
14
+ const fileUpload = v.pipe(v.custom(isFileUpload, `Expected a FileUpload object`), v.title(`fileUpload`));
15
+ /**
16
+ * Walks a value and returns all {@link FileUpload}s within it, along
17
+ * with the path each one occupies.
18
+ */
19
+ const collectFileUploads = (val, path = []) => {
20
+ if (isFileUpload(val)) return [{
21
+ path,
22
+ file: val
23
+ }];
24
+ if (Array.isArray(val)) return val.flatMap((item, i) => collectFileUploads(item, [...path, i]));
25
+ if (isObject(val)) return Object.entries(val).flatMap(([key, item]) => collectFileUploads(item, [...path, key]));
26
+ return [];
27
+ };
28
+ /**
29
+ * Returns a deep copy of `body` with the value at `path` replaced by
30
+ * `replacement`. Pure: never mutates `body` or any of its children.
31
+ */
32
+ const replaceAtPath = (body, path, replacement) => {
33
+ if (path.length === 0) return replacement;
34
+ const [head, ...rest] = path;
35
+ if (Array.isArray(body)) return body.map((item, index) => index === head ? replaceAtPath(item, rest, replacement) : item);
36
+ if (isObject(body)) return Object.fromEntries(Object.entries(body).map(([key, item]) => [key, key === head ? replaceAtPath(item, rest, replacement) : item]));
37
+ return body;
38
+ };
39
+ /**
40
+ * Given a body that contains one or more {@link FileUpload}s, produce
41
+ * a `FormData` payload Discord can consume.
42
+ *
43
+ * Files are appended as `files[n]` parts; the rest of the body is
44
+ * snake_cased and JSON-stringified into a `payload_json` part.
45
+ *
46
+ * Each FileUpload in the body is replaced by its attachment placeholder
47
+ * `{ id: n }` so that an `attachments` array (if present) can reference
48
+ * uploads by index. Discord matches these placeholders to the
49
+ * corresponding `files[n]` parts.
50
+ */
51
+ const toMultipartBody = (body, toSnakeKeys) => {
52
+ const uploads = collectFileUploads(body);
53
+ if (uploads.length === 0) throw new Error(`toMultipartBody called with a body containing no FileUploads`);
54
+ const payload = uploads.reduce((acc, { path }, index) => replaceAtPath(acc, path, { id: index }), body);
55
+ const fileEntries = uploads.map(({ file }, index) => {
56
+ const blob = file.contentType && file.content.type !== file.contentType ? new Blob([file.content], { type: file.contentType }) : file.content;
57
+ return [
58
+ `files[${index}]`,
59
+ blob,
60
+ file.filename
61
+ ];
62
+ });
63
+ const payloadJson = new Blob([JSON.stringify(toSnakeKeys(payload))], { type: `application/json` });
64
+ const form = new FormData();
65
+ fileEntries.forEach(([name, blob, filename]) => form.append(name, blob, filename));
66
+ form.append(`payload_json`, payloadJson);
67
+ return form;
68
+ };
69
+ /**
70
+ * Sentinel symbol used to mark a validated body as multipart-eligible.
71
+ * Read by the request layer at serialization time.
72
+ *
73
+ * The marker is attached as a non-enumerable property on the parsed
74
+ * body so it doesn't leak into JSON serialization or the TypeScript
75
+ * output type.
76
+ */
77
+ const MULTIPART_MARKER = Symbol.for(`@discordkit/core/multipart`);
78
+ /**
79
+ * Returns true if `body` should be serialized as `multipart/form-data`.
80
+ *
81
+ * Two signals trigger multipart serialization:
82
+ *
83
+ * 1. **Schema-tagged** — the body was parsed by a {@link multipart}-wrapped
84
+ * schema and at least one {@link FileUpload} was present. The wrapper
85
+ * stamps a non-enumerable {@link MULTIPART_MARKER} on the parsed value.
86
+ * This is the fast path for the validated flow (e.g., `toValidated`).
87
+ *
88
+ * 2. **Value-detected** — the body contains a {@link FileUpload} anywhere
89
+ * in its shape, regardless of whether it was validated. This safety net
90
+ * keeps consumers who bypass validation from silently dropping their
91
+ * files into a JSON body where `Blob` would serialize as `{}`.
92
+ *
93
+ * Either signal switches the request to multipart.
94
+ */
95
+ const shouldSerializeAsMultipart = (body) => {
96
+ if (typeof body !== `object` || body === null) return false;
97
+ if (body[MULTIPART_MARKER] === true) return true;
98
+ return collectFileUploads(body).length > 0;
99
+ };
100
+ function multipart(entries, options) {
101
+ const base = v.object(entries);
102
+ const inner = options?.partial ? v.partial(base) : base;
103
+ return v.pipe(inner, v.transform((parsed) => {
104
+ if (!(collectFileUploads(parsed).length > 0)) return parsed;
105
+ return Object.defineProperty(parsed, MULTIPART_MARKER, {
106
+ value: true,
107
+ enumerable: false,
108
+ configurable: false,
109
+ writable: false
110
+ });
111
+ }));
112
+ }
113
+ //#endregion
114
+ export { MULTIPART_MARKER, collectFileUploads, fileUpload, isFileUpload, multipart, shouldSerializeAsMultipart, toMultipartBody };
115
+
116
+ //# sourceMappingURL=fileUpload.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUpload.mjs","names":[],"sources":["../../src/validations/fileUpload.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport { isObject } from \"../utils/isObject.js\";\n\n/**\n * The shape of a single file upload — used wherever a Discord endpoint\n * accepts an attached file via `multipart/form-data`.\n *\n * @example\n * ```ts\n * await executeWebhook({\n * webhook: \"...\",\n * token: \"...\",\n * body: {\n * content: \"Look at this!\",\n * files: [\n * { filename: \"photo.png\", content: new Blob([bytes], { type: \"image/png\" }) }\n * ]\n * }\n * });\n * ```\n */\nexport interface FileUpload {\n /** Filename including extension. Required for the multipart `Content-Disposition` header. */\n filename: string;\n /** The binary content. Accepts a web-standard `Blob` or `File`. */\n content: Blob;\n /** Optional MIME type. If omitted, taken from the `Blob`'s `type` property. */\n contentType?: string;\n}\n\n/** Type guard — true if `val` looks like a {@link FileUpload}. */\nexport const isFileUpload = (val: unknown): val is FileUpload => {\n if (!isObject(val)) return false;\n // Blob is a global in Node 18+, the browser, and all current runtimes.\n // We test via duck-typing on `arrayBuffer` to avoid the `instanceof`\n // cross-realm pitfall.\n const content = val.content as { arrayBuffer?: unknown } | undefined;\n return (\n typeof val.filename === `string` &&\n typeof content?.arrayBuffer === `function`\n );\n};\n\n/**\n * Valibot schema for a single file upload. Validates the shape and\n * surfaces a clean TypeScript type to consumers.\n */\nexport const fileUpload: v.GenericSchema<FileUpload> = v.pipe(\n v.custom<FileUpload>(isFileUpload, `Expected a FileUpload object`),\n v.title(`fileUpload`)\n);\n\n/**\n * Walks a value and returns all {@link FileUpload}s within it, along\n * with the path each one occupies.\n */\nexport const collectFileUploads = (\n val: unknown,\n path: ReadonlyArray<string | number> = []\n): ReadonlyArray<{\n readonly path: ReadonlyArray<string | number>;\n readonly file: FileUpload;\n}> => {\n if (isFileUpload(val)) return [{ path, file: val }];\n if (Array.isArray(val)) {\n return val.flatMap((item, i) => collectFileUploads(item, [...path, i]));\n }\n if (isObject(val)) {\n return Object.entries(val).flatMap(([key, item]) =>\n collectFileUploads(item, [...path, key])\n );\n }\n return [];\n};\n\n/**\n * Returns a deep copy of `body` with the value at `path` replaced by\n * `replacement`. Pure: never mutates `body` or any of its children.\n */\nconst replaceAtPath = (\n body: unknown,\n path: ReadonlyArray<string | number>,\n replacement: unknown\n): unknown => {\n if (path.length === 0) return replacement;\n const [head, ...rest] = path;\n if (Array.isArray(body)) {\n return body.map((item, index) =>\n index === head ? replaceAtPath(item, rest, replacement) : item\n );\n }\n if (isObject(body)) {\n return Object.fromEntries(\n Object.entries(body).map(([key, item]) => [\n key,\n key === head ? replaceAtPath(item, rest, replacement) : item\n ])\n );\n }\n return body;\n};\n\n/**\n * Given a body that contains one or more {@link FileUpload}s, produce\n * a `FormData` payload Discord can consume.\n *\n * Files are appended as `files[n]` parts; the rest of the body is\n * snake_cased and JSON-stringified into a `payload_json` part.\n *\n * Each FileUpload in the body is replaced by its attachment placeholder\n * `{ id: n }` so that an `attachments` array (if present) can reference\n * uploads by index. Discord matches these placeholders to the\n * corresponding `files[n]` parts.\n */\nexport const toMultipartBody = (\n body: unknown,\n // Loose enough to accept the real `toSnakeKeys` signature\n // (`<T extends object>(o: T) => SnakeKeys<T>`).\n // We cast at the call site since the payload is structurally an object.\n toSnakeKeys: (val: object) => unknown\n): FormData => {\n const uploads = collectFileUploads(body);\n if (uploads.length === 0) {\n throw new Error(\n `toMultipartBody called with a body containing no FileUploads`\n );\n }\n // Build the payload immutably: fold each upload's placeholder into the body.\n const payload = uploads.reduce<unknown>(\n (acc, { path }, index) => replaceAtPath(acc, path, { id: index }),\n body\n );\n // Compose the FormData parts.\n const fileEntries = uploads.map(({ file }, index) => {\n const blob =\n file.contentType && file.content.type !== file.contentType\n ? new Blob([file.content], { type: file.contentType })\n : file.content;\n return [`files[${index}]`, blob, file.filename] as const;\n });\n // `payload` is `unknown` from the reduce; structurally it's always\n // the same shape as `body`, which must be an object to contain uploads.\n const payloadJson = new Blob(\n [JSON.stringify(toSnakeKeys(payload as object))],\n { type: `application/json` }\n );\n // The single side-effect: append parts to the FormData sink.\n const form = new FormData();\n fileEntries.forEach(([name, blob, filename]) =>\n form.append(name, blob, filename)\n );\n form.append(`payload_json`, payloadJson);\n return form;\n};\n\n/**\n * Sentinel symbol used to mark a validated body as multipart-eligible.\n * Read by the request layer at serialization time.\n *\n * The marker is attached as a non-enumerable property on the parsed\n * body so it doesn't leak into JSON serialization or the TypeScript\n * output type.\n */\nexport const MULTIPART_MARKER = Symbol.for(`@discordkit/core/multipart`);\n\n/**\n * Returns true if `body` should be serialized as `multipart/form-data`.\n *\n * Two signals trigger multipart serialization:\n *\n * 1. **Schema-tagged** — the body was parsed by a {@link multipart}-wrapped\n * schema and at least one {@link FileUpload} was present. The wrapper\n * stamps a non-enumerable {@link MULTIPART_MARKER} on the parsed value.\n * This is the fast path for the validated flow (e.g., `toValidated`).\n *\n * 2. **Value-detected** — the body contains a {@link FileUpload} anywhere\n * in its shape, regardless of whether it was validated. This safety net\n * keeps consumers who bypass validation from silently dropping their\n * files into a JSON body where `Blob` would serialize as `{}`.\n *\n * Either signal switches the request to multipart.\n */\nexport const shouldSerializeAsMultipart = (body: unknown): boolean => {\n if (typeof body !== `object` || body === null) return false;\n if ((body as Record<symbol, unknown>)[MULTIPART_MARKER] === true) return true;\n return collectFileUploads(body).length > 0;\n};\n\n/**\n * Wraps an object schema to mark its body as a potential multipart payload.\n *\n * Use {@link multipart} instead of `v.object` whenever an endpoint's body\n * may contain one or more {@link fileUpload} fields (or arrays of them,\n * or optional uploads). The wrapper validates the same shape as\n * `v.object(entries)`. At validation time, the wrapper inspects the\n * parsed body for {@link FileUpload}s. If any are present, it stamps a\n * non-enumerable {@link MULTIPART_MARKER} on the result; the request\n * layer reads that marker at serialization time to choose between\n * `multipart/form-data` (marker present) and `application/json`\n * (marker absent).\n *\n * Pass `{ partial: true }` for endpoints where every field is optional —\n * the wrapper applies `v.partial(...)` to the inner object before piping\n * the transform. `v.partial` itself can't wrap the piped result (it only\n * accepts plain object schemas), so the option lives here.\n *\n * @example\n * ```ts\n * import { multipart, fileUpload } from \"@discordkit/core\";\n * import * as v from \"valibot\";\n *\n * export const updateAvatarSchema = v.object({\n * body: multipart({\n * avatar: v.exactOptional(fileUpload),\n * bio: v.exactOptional(v.string())\n * })\n * });\n *\n * // Every field optional:\n * export const editMessageSchema = v.object({\n * body: multipart(\n * { content: v.string(), files: v.array(fileUpload) },\n * { partial: true }\n * )\n * });\n * ```\n */\nexport function multipart<TEntries extends v.ObjectEntries>(\n entries: TEntries\n): v.GenericSchema<v.InferOutput<v.ObjectSchema<TEntries, undefined>>>;\nexport function multipart<TEntries extends v.ObjectEntries>(\n entries: TEntries,\n options: { partial: true }\n): v.GenericSchema<\n v.InferOutput<\n v.SchemaWithPartial<v.ObjectSchema<TEntries, undefined>, undefined>\n >\n>;\nexport function multipart<TEntries extends v.ObjectEntries>(\n entries: TEntries,\n options?: { partial?: boolean }\n): v.GenericSchema {\n const base = v.object(entries);\n const inner = options?.partial ? v.partial(base) : base;\n // Wrap with a transform that stamps the marker if any FileUploads are present.\n return v.pipe(\n inner,\n v.transform((parsed) => {\n const hasFiles = collectFileUploads(parsed).length > 0;\n if (!hasFiles) return parsed;\n return Object.defineProperty(parsed, MULTIPART_MARKER, {\n value: true,\n enumerable: false,\n configurable: false,\n writable: false\n });\n })\n );\n}\n"],"mappings":";;;;AA+BA,MAAa,gBAAgB,QAAoC;CAC/D,IAAI,CAAC,SAAS,GAAG,GAAG,OAAO;CAI3B,MAAM,UAAU,IAAI;CACpB,OACE,OAAO,IAAI,aAAa,YACxB,OAAO,SAAS,gBAAgB;AAEpC;;;;;AAMA,MAAa,aAA0C,EAAE,KACvD,EAAE,OAAmB,cAAc,8BAA8B,GACjE,EAAE,MAAM,YAAY,CACtB;;;;;AAMA,MAAa,sBACX,KACA,OAAuC,CAAC,MAIpC;CACJ,IAAI,aAAa,GAAG,GAAG,OAAO,CAAC;EAAE;EAAM,MAAM;CAAI,CAAC;CAClD,IAAI,MAAM,QAAQ,GAAG,GACnB,OAAO,IAAI,SAAS,MAAM,MAAM,mBAAmB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;CAExE,IAAI,SAAS,GAAG,GACd,OAAO,OAAO,QAAQ,GAAG,EAAE,SAAS,CAAC,KAAK,UACxC,mBAAmB,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CACzC;CAEF,OAAO,CAAC;AACV;;;;;AAMA,MAAM,iBACJ,MACA,MACA,gBACY;CACZ,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,KAAK,KAAK,MAAM,UACrB,UAAU,OAAO,cAAc,MAAM,MAAM,WAAW,IAAI,IAC5D;CAEF,IAAI,SAAS,IAAI,GACf,OAAO,OAAO,YACZ,OAAO,QAAQ,IAAI,EAAE,KAAK,CAAC,KAAK,UAAU,CACxC,KACA,QAAQ,OAAO,cAAc,MAAM,MAAM,WAAW,IAAI,IAC1D,CAAC,CACH;CAEF,OAAO;AACT;;;;;;;;;;;;;AAcA,MAAa,mBACX,MAIA,gBACa;CACb,MAAM,UAAU,mBAAmB,IAAI;CACvC,IAAI,QAAQ,WAAW,GACrB,MAAM,IAAI,MACR,8DACF;CAGF,MAAM,UAAU,QAAQ,QACrB,KAAK,EAAE,QAAQ,UAAU,cAAc,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,GAChE,IACF;CAEA,MAAM,cAAc,QAAQ,KAAK,EAAE,QAAQ,UAAU;EACnD,MAAM,OACJ,KAAK,eAAe,KAAK,QAAQ,SAAS,KAAK,cAC3C,IAAI,KAAK,CAAC,KAAK,OAAO,GAAG,EAAE,MAAM,KAAK,YAAY,CAAC,IACnD,KAAK;EACX,OAAO;GAAC,SAAS,MAAM;GAAI;GAAM,KAAK;EAAQ;CAChD,CAAC;CAGD,MAAM,cAAc,IAAI,KACtB,CAAC,KAAK,UAAU,YAAY,OAAiB,CAAC,CAAC,GAC/C,EAAE,MAAM,mBAAmB,CAC7B;CAEA,MAAM,OAAO,IAAI,SAAS;CAC1B,YAAY,SAAS,CAAC,MAAM,MAAM,cAChC,KAAK,OAAO,MAAM,MAAM,QAAQ,CAClC;CACA,KAAK,OAAO,gBAAgB,WAAW;CACvC,OAAO;AACT;;;;;;;;;AAUA,MAAa,mBAAmB,OAAO,IAAI,4BAA4B;;;;;;;;;;;;;;;;;;AAmBvE,MAAa,8BAA8B,SAA2B;CACpE,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO;CACtD,IAAK,KAAiC,sBAAsB,MAAM,OAAO;CACzE,OAAO,mBAAmB,IAAI,EAAE,SAAS;AAC3C;AAoDA,SAAgB,UACd,SACA,SACiB;CACjB,MAAM,OAAO,EAAE,OAAO,OAAO;CAC7B,MAAM,QAAQ,SAAS,UAAU,EAAE,QAAQ,IAAI,IAAI;CAEnD,OAAO,EAAE,KACP,OACA,EAAE,WAAW,WAAW;EAEtB,IAAI,EADa,mBAAmB,MAAM,EAAE,SAAS,IACtC,OAAO;EACtB,OAAO,OAAO,eAAe,QAAQ,kBAAkB;GACrD,OAAO;GACP,YAAY;GACZ,cAAc;GACd,UAAU;EACZ,CAAC;CACH,CAAC,CACH;AACF"}
@@ -0,0 +1,17 @@
1
+ import { CheckAction } from "valibot";
2
+
3
+ //#region src/validations/hasMimeType.d.ts
4
+ /**
5
+ * Validation action to check if the given `datauri` string
6
+ * has one of the provided [MIME types](https://en.wikipedia.org/wiki/Media_type)
7
+ *
8
+ * @__NO_SIDE_EFFECTS__
9
+ */
10
+ declare const hasMimeType: (/** an array of MIME types to validate against */
11
+
12
+ requirement: Array<`${string}/${string}`>, /** an optional error message on failed validation */
13
+
14
+ message?: "Received badly formatted Data URI") => CheckAction<string, typeof message>;
15
+ //#endregion
16
+ export { hasMimeType };
17
+ //# sourceMappingURL=hasMimeType.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hasMimeType.d.mts","names":[],"sources":["../../src/validations/hasMimeType.ts"],"mappings":";;;;;AASA;;;;cAAa,WAAA;;AAEX,WAAA,EAAa,KAAA;;AAEb,OAAA,2CACC,WAAA,gBAA2B,OAAA"}
@@ -0,0 +1,18 @@
1
+ import { extractDataURIMetadata } from "./datauri.mjs";
2
+ import { check } from "valibot";
3
+ //#region src/validations/hasMimeType.ts
4
+ /**
5
+ * Validation action to check if the given `datauri` string
6
+ * has one of the provided [MIME types](https://en.wikipedia.org/wiki/Media_type)
7
+ *
8
+ * @__NO_SIDE_EFFECTS__
9
+ */
10
+ const hasMimeType = (requirement, message = `Received badly formatted Data URI`) => check((input) => {
11
+ const { mimeType } = extractDataURIMetadata(input);
12
+ if (typeof mimeType === `undefined`) return false;
13
+ return requirement.includes(mimeType);
14
+ }, message);
15
+ //#endregion
16
+ export { hasMimeType };
17
+
18
+ //# sourceMappingURL=hasMimeType.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hasMimeType.mjs","names":[],"sources":["../../src/validations/hasMimeType.ts"],"sourcesContent":["import { check, type CheckAction } from \"valibot\";\nimport { extractDataURIMetadata } from \"./datauri.js\";\n\n/**\n * Validation action to check if the given `datauri` string\n * has one of the provided [MIME types](https://en.wikipedia.org/wiki/Media_type)\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const hasMimeType = (\n /** an array of MIME types to validate against */\n requirement: Array<`${string}/${string}`>,\n /** an optional error message on failed validation */\n message = `Received badly formatted Data URI` as const\n): CheckAction<string, typeof message> =>\n check((input: string) => {\n const { mimeType } = extractDataURIMetadata(input);\n if (typeof mimeType === `undefined`) {\n return false;\n }\n return requirement.includes(mimeType);\n }, message);\n"],"mappings":";;;;;;;;;AASA,MAAa,eAEX,aAEA,UAAU,wCAEV,OAAO,UAAkB;CACvB,MAAM,EAAE,aAAa,uBAAuB,KAAK;CACjD,IAAI,OAAO,aAAa,aACtB,OAAO;CAET,OAAO,YAAY,SAAS,QAAQ;AACtC,GAAG,OAAO"}