@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.
- package/CHANGELOG.md +423 -0
- package/README.md +52 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.mjs +23 -0
- package/dist/requests/DiscordSession.d.mts +72 -0
- package/dist/requests/DiscordSession.d.mts.map +1 -0
- package/dist/requests/DiscordSession.mjs +262 -0
- package/dist/requests/DiscordSession.mjs.map +1 -0
- package/dist/requests/addParams.d.mts +16 -0
- package/dist/requests/addParams.d.mts.map +1 -0
- package/dist/requests/addParams.mjs +26 -0
- package/dist/requests/addParams.mjs.map +1 -0
- package/dist/requests/buildURL.d.mts +8 -0
- package/dist/requests/buildURL.d.mts.map +1 -0
- package/dist/requests/buildURL.mjs +9 -0
- package/dist/requests/buildURL.mjs.map +1 -0
- package/dist/requests/getAsset.d.mts +8 -0
- package/dist/requests/getAsset.d.mts.map +1 -0
- package/dist/requests/getAsset.mjs +8 -0
- package/dist/requests/getAsset.mjs.map +1 -0
- package/dist/requests/index.d.mts +9 -0
- package/dist/requests/index.mjs +9 -0
- package/dist/requests/methods.d.mts +64 -0
- package/dist/requests/methods.d.mts.map +1 -0
- package/dist/requests/methods.mjs +12 -0
- package/dist/requests/methods.mjs.map +1 -0
- package/dist/requests/request.d.mts +28 -0
- package/dist/requests/request.d.mts.map +1 -0
- package/dist/requests/request.mjs +31 -0
- package/dist/requests/request.mjs.map +1 -0
- package/dist/requests/toProcedure.d.mts +41 -0
- package/dist/requests/toProcedure.d.mts.map +1 -0
- package/dist/requests/toProcedure.mjs +29 -0
- package/dist/requests/toProcedure.mjs.map +1 -0
- package/dist/requests/toQuery.d.mts +37 -0
- package/dist/requests/toQuery.d.mts.map +1 -0
- package/dist/requests/toQuery.mjs +10 -0
- package/dist/requests/toQuery.mjs.map +1 -0
- package/dist/requests/toValidated.d.mts +17 -0
- package/dist/requests/toValidated.d.mts.map +1 -0
- package/dist/requests/toValidated.mjs +27 -0
- package/dist/requests/toValidated.mjs.map +1 -0
- package/dist/requests/{verifyKey.d.ts → verifyKey.d.mts} +5 -1
- package/dist/requests/verifyKey.d.mts.map +1 -0
- package/dist/requests/verifyKey.mjs +64 -0
- package/dist/requests/verifyKey.mjs.map +1 -0
- package/dist/utils/isBetween.d.mts +5 -0
- package/dist/utils/isBetween.d.mts.map +1 -0
- package/dist/utils/isBetween.mjs +6 -0
- package/dist/utils/isBetween.mjs.map +1 -0
- package/dist/utils/{isNonNullable.js → isNonNullable.d.mts} +6 -2
- package/dist/utils/isNonNullable.d.mts.map +1 -0
- package/dist/utils/isNonNullable.mjs +24 -0
- package/dist/utils/isNonNullable.mjs.map +1 -0
- package/dist/utils/isNumericString.d.mts +5 -0
- package/dist/utils/isNumericString.d.mts.map +1 -0
- package/dist/utils/isNumericString.mjs +6 -0
- package/dist/utils/isNumericString.mjs.map +1 -0
- package/dist/utils/isObject.d.mts +5 -0
- package/dist/utils/isObject.d.mts.map +1 -0
- package/dist/utils/isObject.mjs +6 -0
- package/dist/utils/isObject.mjs.map +1 -0
- package/dist/utils/sleep.d.mts +8 -0
- package/dist/utils/sleep.d.mts.map +1 -0
- package/dist/utils/sleep.mjs +9 -0
- package/dist/utils/sleep.mjs.map +1 -0
- package/dist/utils/toCamelCase.d.mts +5 -0
- package/dist/utils/toCamelCase.d.mts.map +1 -0
- package/dist/utils/toCamelCase.mjs +6 -0
- package/dist/utils/toCamelCase.mjs.map +1 -0
- package/dist/utils/toCamelKeys.d.mts +20 -0
- package/dist/utils/toCamelKeys.d.mts.map +1 -0
- package/dist/utils/toCamelKeys.mjs +15 -0
- package/dist/utils/toCamelKeys.mjs.map +1 -0
- package/dist/utils/toSnakeCase.d.mts +5 -0
- package/dist/utils/toSnakeCase.d.mts.map +1 -0
- package/dist/utils/toSnakeCase.mjs +6 -0
- package/dist/utils/toSnakeCase.mjs.map +1 -0
- package/dist/utils/toSnakeKeys.d.mts +24 -0
- package/dist/utils/toSnakeKeys.d.mts.map +1 -0
- package/dist/utils/toSnakeKeys.mjs +15 -0
- package/dist/utils/toSnakeKeys.mjs.map +1 -0
- package/dist/validations/asDigits.d.mts +13 -0
- package/dist/validations/asDigits.d.mts.map +1 -0
- package/dist/validations/asDigits.mjs +12 -0
- package/dist/validations/asDigits.mjs.map +1 -0
- package/dist/validations/asInteger.d.mts +13 -0
- package/dist/validations/asInteger.d.mts.map +1 -0
- package/dist/validations/asInteger.mjs +12 -0
- package/dist/validations/asInteger.mjs.map +1 -0
- package/dist/validations/bitfield.d.mts +24 -0
- package/dist/validations/bitfield.d.mts.map +1 -0
- package/dist/validations/bitfield.mjs +22 -0
- package/dist/validations/bitfield.mjs.map +1 -0
- package/dist/validations/boundedArray.d.mts +14 -0
- package/dist/validations/boundedArray.d.mts.map +1 -0
- package/dist/validations/boundedArray.mjs +11 -0
- package/dist/validations/boundedArray.mjs.map +1 -0
- package/dist/validations/boundedInteger.d.mts +14 -0
- package/dist/validations/boundedInteger.d.mts.map +1 -0
- package/dist/validations/boundedInteger.mjs +11 -0
- package/dist/validations/boundedInteger.mjs.map +1 -0
- package/dist/validations/boundedString.d.mts +15 -0
- package/dist/validations/boundedString.d.mts.map +1 -0
- package/dist/validations/boundedString.mjs +12 -0
- package/dist/validations/boundedString.mjs.map +1 -0
- package/dist/validations/datauri.d.mts +25 -0
- package/dist/validations/datauri.d.mts.map +1 -0
- package/dist/validations/datauri.mjs +19 -0
- package/dist/validations/datauri.mjs.map +1 -0
- package/dist/validations/fileUpload.d.mts +130 -0
- package/dist/validations/fileUpload.d.mts.map +1 -0
- package/dist/validations/fileUpload.mjs +116 -0
- package/dist/validations/fileUpload.mjs.map +1 -0
- package/dist/validations/hasMimeType.d.mts +17 -0
- package/dist/validations/hasMimeType.d.mts.map +1 -0
- package/dist/validations/hasMimeType.mjs +18 -0
- package/dist/validations/hasMimeType.mjs.map +1 -0
- package/dist/validations/hasSize.d.mts +11 -0
- package/dist/validations/hasSize.d.mts.map +1 -0
- package/dist/validations/hasSize.mjs +14 -0
- package/dist/validations/hasSize.mjs.map +1 -0
- package/dist/validations/index.d.mts +15 -0
- package/dist/validations/index.mjs +15 -0
- package/dist/validations/schema.d.mts +103 -0
- package/dist/validations/schema.d.mts.map +1 -0
- package/dist/validations/schema.mjs +111 -0
- package/dist/validations/schema.mjs.map +1 -0
- package/dist/validations/{snowflake.d.ts → snowflake.d.mts} +10 -7
- package/dist/validations/snowflake.d.mts.map +1 -0
- package/dist/validations/snowflake.mjs +30 -0
- package/dist/validations/snowflake.mjs.map +1 -0
- package/dist/validations/timestamp.d.mts +8 -0
- package/dist/validations/timestamp.d.mts.map +1 -0
- package/dist/validations/timestamp.mjs +8 -0
- package/dist/validations/timestamp.mjs.map +1 -0
- package/dist/validations/toBlob.d.mts +8 -0
- package/dist/validations/toBlob.d.mts.map +1 -0
- package/dist/validations/toBlob.mjs +19 -0
- package/dist/validations/toBlob.mjs.map +1 -0
- package/dist/validations/url.d.mts +7 -0
- package/dist/validations/url.d.mts.map +1 -0
- package/dist/validations/url.mjs +7 -0
- package/dist/validations/url.mjs.map +1 -0
- package/package.json +10 -23
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -3
- package/dist/index.js.map +0 -1
- package/dist/requests/DiscordSession.d.ts +0 -25
- package/dist/requests/DiscordSession.js +0 -255
- package/dist/requests/DiscordSession.js.map +0 -1
- package/dist/requests/addParams.d.ts +0 -2
- package/dist/requests/addParams.js +0 -11
- package/dist/requests/addParams.js.map +0 -1
- package/dist/requests/buildURL.d.ts +0 -2
- package/dist/requests/buildURL.js +0 -4
- package/dist/requests/buildURL.js.map +0 -1
- package/dist/requests/getAsset.d.ts +0 -2
- package/dist/requests/getAsset.js +0 -3
- package/dist/requests/getAsset.js.map +0 -1
- package/dist/requests/index.d.ts +0 -8
- package/dist/requests/index.js +0 -9
- package/dist/requests/index.js.map +0 -1
- package/dist/requests/methods.d.ts +0 -13
- package/dist/requests/methods.js +0 -8
- package/dist/requests/methods.js.map +0 -1
- package/dist/requests/request.d.ts +0 -2
- package/dist/requests/request.js +0 -30
- package/dist/requests/request.js.map +0 -1
- package/dist/requests/toProcedure.d.ts +0 -31
- package/dist/requests/toProcedure.js +0 -36
- package/dist/requests/toProcedure.js.map +0 -1
- package/dist/requests/toQuery.d.ts +0 -28
- package/dist/requests/toQuery.js +0 -9
- package/dist/requests/toQuery.js.map +0 -1
- package/dist/requests/toValidated.d.ts +0 -13
- package/dist/requests/toValidated.js +0 -29
- package/dist/requests/toValidated.js.map +0 -1
- package/dist/requests/verifyKey.js +0 -91
- package/dist/requests/verifyKey.js.map +0 -1
- package/dist/utils/isBetween.d.ts +0 -1
- package/dist/utils/isBetween.js +0 -2
- package/dist/utils/isBetween.js.map +0 -1
- package/dist/utils/isNonNullable.d.ts +0 -20
- package/dist/utils/isNonNullable.js.map +0 -1
- package/dist/utils/isNumericString.d.ts +0 -1
- package/dist/utils/isNumericString.js +0 -2
- package/dist/utils/isNumericString.js.map +0 -1
- package/dist/utils/isObject.d.ts +0 -1
- package/dist/utils/isObject.js +0 -2
- package/dist/utils/isObject.js.map +0 -1
- package/dist/utils/sleep.d.ts +0 -4
- package/dist/utils/sleep.js +0 -5
- package/dist/utils/sleep.js.map +0 -1
- package/dist/utils/toCamelCase.d.ts +0 -1
- package/dist/utils/toCamelCase.js +0 -2
- package/dist/utils/toCamelCase.js.map +0 -1
- package/dist/utils/toCamelKeys.d.ts +0 -2
- package/dist/utils/toCamelKeys.js +0 -16
- package/dist/utils/toCamelKeys.js.map +0 -1
- package/dist/utils/toSnakeCase.d.ts +0 -1
- package/dist/utils/toSnakeCase.js +0 -4
- package/dist/utils/toSnakeCase.js.map +0 -1
- package/dist/utils/toSnakeKeys.d.ts +0 -2
- package/dist/utils/toSnakeKeys.js +0 -16
- package/dist/utils/toSnakeKeys.js.map +0 -1
- package/dist/validations/asDigits.d.ts +0 -6
- package/dist/validations/asDigits.js +0 -6
- package/dist/validations/asDigits.js.map +0 -1
- package/dist/validations/asInteger.d.ts +0 -6
- package/dist/validations/asInteger.js +0 -6
- package/dist/validations/asInteger.js.map +0 -1
- package/dist/validations/bitfield.d.ts +0 -17
- package/dist/validations/bitfield.js +0 -37
- package/dist/validations/bitfield.js.map +0 -1
- package/dist/validations/boundedArray.d.ts +0 -6
- package/dist/validations/boundedArray.js +0 -8
- package/dist/validations/boundedArray.js.map +0 -1
- package/dist/validations/boundedInteger.d.ts +0 -6
- package/dist/validations/boundedInteger.js +0 -8
- package/dist/validations/boundedInteger.js.map +0 -1
- package/dist/validations/boundedString.d.ts +0 -6
- package/dist/validations/boundedString.js +0 -8
- package/dist/validations/boundedString.js.map +0 -1
- package/dist/validations/datauri.d.ts +0 -20
- package/dist/validations/datauri.js +0 -20
- package/dist/validations/datauri.js.map +0 -1
- package/dist/validations/hasMimeType.d.ts +0 -10
- package/dist/validations/hasMimeType.js +0 -18
- package/dist/validations/hasMimeType.js.map +0 -1
- package/dist/validations/hasSize.d.ts +0 -5
- package/dist/validations/hasSize.js +0 -13
- package/dist/validations/hasSize.js.map +0 -1
- package/dist/validations/index.d.ts +0 -12
- package/dist/validations/index.js +0 -13
- package/dist/validations/index.js.map +0 -1
- package/dist/validations/snowflake.js +0 -39
- package/dist/validations/snowflake.js.map +0 -1
- package/dist/validations/timestamp.d.ts +0 -3
- package/dist/validations/timestamp.js +0 -4
- package/dist/validations/timestamp.js.map +0 -1
- package/dist/validations/toBlob.d.ts +0 -4
- package/dist/validations/toBlob.js +0 -19
- package/dist/validations/toBlob.js.map +0 -1
- package/dist/validations/url.d.ts +0 -2
- package/dist/validations/url.js +0 -3
- 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"}
|