@discordkit/core 4.0.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 +7 -0
- package/dist/requests/DiscordSession.d.mts +43 -1
- package/dist/requests/DiscordSession.d.mts.map +1 -0
- package/dist/requests/DiscordSession.mjs +61 -1
- package/dist/requests/DiscordSession.mjs.map +1 -0
- package/dist/requests/addParams.d.mts +2 -1
- package/dist/requests/addParams.d.mts.map +1 -0
- package/dist/requests/addParams.mjs +2 -0
- package/dist/requests/addParams.mjs.map +1 -0
- package/dist/requests/buildURL.d.mts +2 -1
- package/dist/requests/buildURL.d.mts.map +1 -0
- package/dist/requests/buildURL.mjs +2 -0
- package/dist/requests/buildURL.mjs.map +1 -0
- package/dist/requests/getAsset.d.mts +2 -1
- package/dist/requests/getAsset.d.mts.map +1 -0
- package/dist/requests/getAsset.mjs +2 -0
- package/dist/requests/getAsset.mjs.map +1 -0
- package/dist/requests/methods.d.mts +2 -1
- package/dist/requests/methods.d.mts.map +1 -0
- package/dist/requests/methods.mjs +2 -0
- package/dist/requests/methods.mjs.map +1 -0
- package/dist/requests/request.d.mts +2 -1
- package/dist/requests/request.d.mts.map +1 -0
- package/dist/requests/request.mjs +3 -1
- package/dist/requests/request.mjs.map +1 -0
- package/dist/requests/toProcedure.d.mts +2 -1
- package/dist/requests/toProcedure.d.mts.map +1 -0
- package/dist/requests/toProcedure.mjs +2 -0
- package/dist/requests/toProcedure.mjs.map +1 -0
- package/dist/requests/toQuery.d.mts +4 -3
- package/dist/requests/toQuery.d.mts.map +1 -0
- package/dist/requests/toQuery.mjs +7 -14
- package/dist/requests/toQuery.mjs.map +1 -0
- package/dist/requests/toValidated.d.mts +2 -1
- package/dist/requests/toValidated.d.mts.map +1 -0
- package/dist/requests/toValidated.mjs +2 -0
- package/dist/requests/toValidated.mjs.map +1 -0
- package/dist/requests/verifyKey.d.mts +2 -1
- package/dist/requests/verifyKey.d.mts.map +1 -0
- package/dist/requests/verifyKey.mjs +6 -5
- package/dist/requests/verifyKey.mjs.map +1 -0
- package/dist/utils/isBetween.d.mts +2 -1
- package/dist/utils/isBetween.d.mts.map +1 -0
- package/dist/utils/isBetween.mjs +2 -0
- package/dist/utils/isBetween.mjs.map +1 -0
- package/dist/utils/isNonNullable.d.mts +2 -1
- package/dist/utils/isNonNullable.d.mts.map +1 -0
- package/dist/utils/isNonNullable.mjs +2 -0
- package/dist/utils/isNonNullable.mjs.map +1 -0
- package/dist/utils/isNumericString.d.mts +2 -1
- package/dist/utils/isNumericString.d.mts.map +1 -0
- package/dist/utils/isNumericString.mjs +2 -0
- package/dist/utils/isNumericString.mjs.map +1 -0
- package/dist/utils/isObject.d.mts +3 -2
- package/dist/utils/isObject.d.mts.map +1 -0
- package/dist/utils/isObject.mjs +2 -0
- package/dist/utils/isObject.mjs.map +1 -0
- package/dist/utils/sleep.d.mts +2 -1
- package/dist/utils/sleep.d.mts.map +1 -0
- package/dist/utils/sleep.mjs +2 -0
- package/dist/utils/sleep.mjs.map +1 -0
- package/dist/utils/toCamelCase.d.mts +2 -1
- package/dist/utils/toCamelCase.d.mts.map +1 -0
- package/dist/utils/toCamelCase.mjs +2 -0
- package/dist/utils/toCamelCase.mjs.map +1 -0
- package/dist/utils/toCamelKeys.d.mts +18 -4
- package/dist/utils/toCamelKeys.d.mts.map +1 -0
- package/dist/utils/toCamelKeys.mjs +2 -0
- package/dist/utils/toCamelKeys.mjs.map +1 -0
- package/dist/utils/toSnakeCase.d.mts +2 -1
- package/dist/utils/toSnakeCase.d.mts.map +1 -0
- package/dist/utils/toSnakeCase.mjs +2 -0
- package/dist/utils/toSnakeCase.mjs.map +1 -0
- package/dist/utils/toSnakeKeys.d.mts +22 -4
- package/dist/utils/toSnakeKeys.d.mts.map +1 -0
- package/dist/utils/toSnakeKeys.mjs +2 -0
- package/dist/utils/toSnakeKeys.mjs.map +1 -0
- package/dist/validations/asDigits.d.mts +2 -1
- package/dist/validations/asDigits.d.mts.map +1 -0
- package/dist/validations/asDigits.mjs +2 -0
- package/dist/validations/asDigits.mjs.map +1 -0
- package/dist/validations/asInteger.d.mts +2 -1
- package/dist/validations/asInteger.d.mts.map +1 -0
- package/dist/validations/asInteger.mjs +2 -0
- package/dist/validations/asInteger.mjs.map +1 -0
- package/dist/validations/bitfield.d.mts +2 -1
- package/dist/validations/bitfield.d.mts.map +1 -0
- package/dist/validations/bitfield.mjs +2 -0
- package/dist/validations/bitfield.mjs.map +1 -0
- package/dist/validations/boundedArray.d.mts +2 -1
- package/dist/validations/boundedArray.d.mts.map +1 -0
- package/dist/validations/boundedArray.mjs +2 -0
- package/dist/validations/boundedArray.mjs.map +1 -0
- package/dist/validations/boundedInteger.d.mts +2 -1
- package/dist/validations/boundedInteger.d.mts.map +1 -0
- package/dist/validations/boundedInteger.mjs +2 -0
- package/dist/validations/boundedInteger.mjs.map +1 -0
- package/dist/validations/boundedString.d.mts +2 -1
- package/dist/validations/boundedString.d.mts.map +1 -0
- package/dist/validations/boundedString.mjs +2 -0
- package/dist/validations/boundedString.mjs.map +1 -0
- package/dist/validations/datauri.d.mts +2 -1
- package/dist/validations/datauri.d.mts.map +1 -0
- package/dist/validations/datauri.mjs +2 -0
- package/dist/validations/datauri.mjs.map +1 -0
- package/dist/validations/fileUpload.d.mts +2 -1
- package/dist/validations/fileUpload.d.mts.map +1 -0
- package/dist/validations/fileUpload.mjs +4 -2
- package/dist/validations/fileUpload.mjs.map +1 -0
- package/dist/validations/hasMimeType.d.mts +2 -1
- package/dist/validations/hasMimeType.d.mts.map +1 -0
- package/dist/validations/hasMimeType.mjs +2 -0
- package/dist/validations/hasMimeType.mjs.map +1 -0
- package/dist/validations/hasSize.d.mts +2 -1
- package/dist/validations/hasSize.d.mts.map +1 -0
- package/dist/validations/hasSize.mjs +2 -0
- package/dist/validations/hasSize.mjs.map +1 -0
- package/dist/validations/schema.d.mts +4 -3
- package/dist/validations/schema.d.mts.map +1 -0
- package/dist/validations/schema.mjs +2 -0
- package/dist/validations/schema.mjs.map +1 -0
- package/dist/validations/snowflake.d.mts +2 -1
- package/dist/validations/snowflake.d.mts.map +1 -0
- package/dist/validations/snowflake.mjs +2 -0
- package/dist/validations/snowflake.mjs.map +1 -0
- package/dist/validations/timestamp.d.mts +2 -1
- package/dist/validations/timestamp.d.mts.map +1 -0
- package/dist/validations/timestamp.mjs +2 -0
- package/dist/validations/timestamp.mjs.map +1 -0
- package/dist/validations/toBlob.d.mts +3 -4
- package/dist/validations/toBlob.d.mts.map +1 -0
- package/dist/validations/toBlob.mjs +2 -0
- package/dist/validations/toBlob.mjs.map +1 -0
- package/dist/validations/url.d.mts +2 -1
- package/dist/validations/url.d.mts.map +1 -0
- package/dist/validations/url.mjs +2 -0
- package/dist/validations/url.mjs.map +1 -0
- package/package.json +3 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isNumericString.mjs","names":[],"sources":["../../src/utils/isNumericString.ts"],"sourcesContent":["export const isNumericString = (val: unknown): val is string =>\n typeof val === `string` && /^\\d+$/.test(val);\n"],"mappings":";AAAA,MAAa,mBAAmB,QAC9B,OAAO,QAAQ,YAAY,QAAQ,KAAK,GAAG"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/utils/isObject.d.ts
|
|
2
|
-
declare const isObject: (val: unknown) => val is
|
|
2
|
+
declare const isObject: (val: unknown) => val is Record<string, unknown>;
|
|
3
3
|
//#endregion
|
|
4
|
-
export { isObject };
|
|
4
|
+
export { isObject };
|
|
5
|
+
//# sourceMappingURL=isObject.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isObject.d.mts","names":[],"sources":["../../src/utils/isObject.ts"],"mappings":";cAAa,QAAA,GAAY,GAAA,cAAe,GAAA,IAAO,MAAM"}
|
package/dist/utils/isObject.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isObject.mjs","names":[],"sources":["../../src/utils/isObject.ts"],"sourcesContent":["export const isObject = (val: unknown): val is Record<string, unknown> =>\n Boolean(val) && typeof val === `object` && !Array.isArray(val);\n"],"mappings":";AAAA,MAAa,YAAY,QACvB,QAAQ,GAAG,KAAK,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG"}
|
package/dist/utils/sleep.d.mts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.d.mts","names":[],"sources":["../../src/utils/sleep.ts"],"mappings":";;AAGA;;cAAa,KAAA,GAAe,EAAA,aAAa,OAAO"}
|
package/dist/utils/sleep.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.mjs","names":[],"sources":["../../src/utils/sleep.ts"],"sourcesContent":["/**\n * Sleep for a given number of milliseconds\n */\nexport const sleep = async (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));\n"],"mappings":";;;;AAGA,MAAa,QAAQ,OAAO,OAC1B,IAAI,SAAS,YAAY,WAAW,SAAS,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toCamelCase.d.mts","names":[],"sources":["../../src/utils/toCamelCase.ts"],"mappings":";cAAa,WAAA,GAAe,GAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toCamelCase.mjs","names":[],"sources":["../../src/utils/toCamelCase.ts"],"sourcesContent":["export const toCamelCase = (str: string): string =>\n str.replace(/_(?<char>[a-zA-Z])/g, (g) => g[1].toUpperCase());\n"],"mappings":";AAAA,MAAa,eAAe,QAC1B,IAAI,QAAQ,wBAAwB,MAAM,EAAE,GAAG,YAAY,CAAC"}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import { CamelCasedPropertiesDeep } from "type-fest";
|
|
2
|
-
|
|
3
1
|
//#region src/utils/toCamelKeys.d.ts
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Convert a `snake_case` string-literal type to `camelCase`, matching exactly
|
|
4
|
+
* what {@link toCamelCase} does at runtime: each `_x` becomes `X`. Self-contained
|
|
5
|
+
* (no general word-splitting); we only ever convert underscore-delimited Discord
|
|
6
|
+
* API keys, so this is all the casing we need.
|
|
7
|
+
*/
|
|
8
|
+
type CamelCase<S extends string> = S extends `${infer Head}_${infer Tail}` ? `${Head}${CamelCase<Capitalize<Tail>>}` : S;
|
|
9
|
+
/**
|
|
10
|
+
* Recursively camel-case the keys of an object/array type. Mirrors
|
|
11
|
+
* {@link toCamelKeys}'s runtime: arrays map element-wise, plain objects remap
|
|
12
|
+
* their keys, and leaf values pass through unchanged. Replaces type-fest's
|
|
13
|
+
* `CamelCasedPropertiesDeep` — narrower (no Set/tuple/options handling) because
|
|
14
|
+
* the only inputs are plain nested Discord API JSON.
|
|
15
|
+
*/
|
|
16
|
+
type CamelKeys<T> = T extends ReadonlyArray<infer U> ? Array<CamelKeys<U>> : T extends object ? { [K in keyof T as K extends string ? CamelCase<K> : K]: CamelKeys<T[K]> } : T;
|
|
17
|
+
declare const toCamelKeys: <T extends object>(o: T) => CamelKeys<T>;
|
|
5
18
|
//#endregion
|
|
6
|
-
export { toCamelKeys };
|
|
19
|
+
export { CamelKeys, toCamelKeys };
|
|
20
|
+
//# sourceMappingURL=toCamelKeys.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toCamelKeys.d.mts","names":[],"sources":["../../src/utils/toCamelKeys.ts"],"mappings":";;;;;;;KASK,SAAA,qBAA8B,CAAA,4CAC5B,IAAA,GAAO,SAAA,CAAU,UAAA,CAAW,IAAA,OAC/B,CAAA;;;;;;;;KASQ,SAAA,MACV,CAAA,SAAU,aAAA,YACN,KAAA,CAAM,SAAA,CAAU,CAAA,KAChB,CAAA,gCAEgB,CAAA,IAAK,CAAA,kBAAmB,SAAA,CAAU,CAAA,IAAK,CAAA,GAAI,SAAA,CACrD,CAAA,CAAE,CAAA,OAGN,CAAA;AAAA,cAEK,WAAA,qBAAiC,CAAA,EAAG,CAAA,KAAI,SAAA,CAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toCamelKeys.mjs","names":[],"sources":["../../src/utils/toCamelKeys.ts"],"sourcesContent":["import { isObject } from \"./isObject.js\";\nimport { toCamelCase } from \"./toCamelCase.js\";\n\n/**\n * Convert a `snake_case` string-literal type to `camelCase`, matching exactly\n * what {@link toCamelCase} does at runtime: each `_x` becomes `X`. Self-contained\n * (no general word-splitting); we only ever convert underscore-delimited Discord\n * API keys, so this is all the casing we need.\n */\ntype CamelCase<S extends string> = S extends `${infer Head}_${infer Tail}`\n ? `${Head}${CamelCase<Capitalize<Tail>>}`\n : S;\n\n/**\n * Recursively camel-case the keys of an object/array type. Mirrors\n * {@link toCamelKeys}'s runtime: arrays map element-wise, plain objects remap\n * their keys, and leaf values pass through unchanged. Replaces type-fest's\n * `CamelCasedPropertiesDeep` — narrower (no Set/tuple/options handling) because\n * the only inputs are plain nested Discord API JSON.\n */\nexport type CamelKeys<T> =\n T extends ReadonlyArray<infer U>\n ? Array<CamelKeys<U>>\n : T extends object\n ? {\n [K in keyof T as K extends string ? CamelCase<K> : K]: CamelKeys<\n T[K]\n >;\n }\n : T;\n\nexport const toCamelKeys = <T extends object>(o: T): CamelKeys<T> => {\n if (Array.isArray(o)) {\n return o.map(toCamelKeys) as CamelKeys<T>;\n } else if (isObject(o)) {\n return Object.entries(o).reduce((acc, [key, value]) => {\n // @ts-expect-error\n acc[toCamelCase(key)] = toCamelKeys(value);\n return acc;\n }, {}) as CamelKeys<T>;\n }\n\n return o as CamelKeys<T>;\n};\n"],"mappings":";;;AA+BA,MAAa,eAAiC,MAAuB;CACnE,IAAI,MAAM,QAAQ,CAAC,GACjB,OAAO,EAAE,IAAI,WAAW;MACnB,IAAI,SAAS,CAAC,GACnB,OAAO,OAAO,QAAQ,CAAC,EAAE,QAAQ,KAAK,CAAC,KAAK,WAAW;EAErD,IAAI,YAAY,GAAG,KAAK,YAAY,KAAK;EACzC,OAAO;CACT,GAAG,CAAC,CAAC;CAGP,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSnakeCase.d.mts","names":[],"sources":["../../src/utils/toSnakeCase.ts"],"mappings":";cAAa,WAAA,GAAe,GAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSnakeCase.mjs","names":[],"sources":["../../src/utils/toSnakeCase.ts"],"sourcesContent":["export const toSnakeCase = (str: string): string =>\n str\n .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\n .substring(str.slice(0, 1).match(/(?<char>[A-Z])/g) ? 1 : 0);\n"],"mappings":";AAAA,MAAa,eAAe,QAC1B,IACG,QAAQ,WAAW,WAAW,IAAI,OAAO,YAAY,GAAG,EACxD,UAAU,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,iBAAiB,IAAI,IAAI,CAAC"}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
import { SnakeCasedPropertiesDeep } from "type-fest";
|
|
2
|
-
|
|
3
1
|
//#region src/utils/toSnakeKeys.d.ts
|
|
4
|
-
|
|
2
|
+
/** The uppercase ASCII letters, for the camel→snake split. */
|
|
3
|
+
type Upper = `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z`;
|
|
4
|
+
/**
|
|
5
|
+
* Walk a `camelCase` literal, inserting `_` before each uppercase letter and
|
|
6
|
+
* lowercasing it — matching {@link toSnakeCase}'s runtime. `Started` tracks
|
|
7
|
+
* whether we've emitted any character yet, so a leading capital (e.g. `Foo`)
|
|
8
|
+
* doesn't get a leading underscore (→ `foo`, not `_foo`).
|
|
9
|
+
*/
|
|
10
|
+
type SnakeWalk<S extends string, Started extends boolean = false> = S extends `${infer Head}${infer Tail}` ? Head extends Upper ? `${Started extends true ? `_` : ``}${Lowercase<Head>}${SnakeWalk<Tail, true>}` : `${Head}${SnakeWalk<Tail, true>}` : S;
|
|
11
|
+
/** Convert a `camelCase` string-literal type to `snake_case`. Self-contained;
|
|
12
|
+
* mirrors {@link toSnakeCase} (the only transform we apply to API keys). */
|
|
13
|
+
type SnakeCase<S extends string> = SnakeWalk<S>;
|
|
14
|
+
/**
|
|
15
|
+
* Recursively snake-case the keys of an object/array type. Mirrors
|
|
16
|
+
* {@link toSnakeKeys}'s runtime. Replaces type-fest's `SnakeCasedPropertiesDeep`
|
|
17
|
+
* — narrower (no Set/tuple/options handling) because the only inputs are plain
|
|
18
|
+
* nested Discord API JSON.
|
|
19
|
+
*/
|
|
20
|
+
type SnakeKeys<T> = T extends ReadonlyArray<infer U> ? Array<SnakeKeys<U>> : T extends object ? { [K in keyof T as K extends string ? SnakeCase<K> : K]: SnakeKeys<T[K]> } : T;
|
|
21
|
+
declare const toSnakeKeys: <T extends object>(o: T) => SnakeKeys<T>;
|
|
5
22
|
//#endregion
|
|
6
|
-
export { toSnakeKeys };
|
|
23
|
+
export { SnakeKeys, toSnakeKeys };
|
|
24
|
+
//# sourceMappingURL=toSnakeKeys.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSnakeKeys.d.mts","names":[],"sources":["../../src/utils/toSnakeKeys.ts"],"mappings":";;KAIK,KAAA;;;;AAAK;AAAA;;KAkCL,SAAA,sDAGD,CAAA,wCACA,IAAA,SAAa,KAAA,MACR,OAAA,2BAAkC,SAAA,CAAU,IAAA,IAAQ,SAAA,CAAU,IAAA,eAC9D,IAAA,GAAO,SAAA,CAAU,IAAA,YACtB,CAAA;;;KAIC,SAAA,qBAA8B,SAAS,CAAC,CAAA;;;;;;;KAQjC,SAAA,MACV,CAAA,SAAU,aAAA,YACN,KAAA,CAAM,SAAA,CAAU,CAAA,KAChB,CAAA,gCAEgB,CAAA,IAAK,CAAA,kBAAmB,SAAA,CAAU,CAAA,IAAK,CAAA,GAAI,SAAA,CACrD,CAAA,CAAE,CAAA,OAGN,CAAA;AAAA,cAEK,WAAA,qBAAiC,CAAA,EAAG,CAAA,KAAI,SAAA,CAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSnakeKeys.mjs","names":[],"sources":["../../src/utils/toSnakeKeys.ts"],"sourcesContent":["import { isObject } from \"./isObject.js\";\nimport { toSnakeCase } from \"./toSnakeCase.js\";\n\n/** The uppercase ASCII letters, for the camel→snake split. */\ntype Upper =\n | `A`\n | `B`\n | `C`\n | `D`\n | `E`\n | `F`\n | `G`\n | `H`\n | `I`\n | `J`\n | `K`\n | `L`\n | `M`\n | `N`\n | `O`\n | `P`\n | `Q`\n | `R`\n | `S`\n | `T`\n | `U`\n | `V`\n | `W`\n | `X`\n | `Y`\n | `Z`;\n\n/**\n * Walk a `camelCase` literal, inserting `_` before each uppercase letter and\n * lowercasing it — matching {@link toSnakeCase}'s runtime. `Started` tracks\n * whether we've emitted any character yet, so a leading capital (e.g. `Foo`)\n * doesn't get a leading underscore (→ `foo`, not `_foo`).\n */\ntype SnakeWalk<\n S extends string,\n Started extends boolean = false\n> = S extends `${infer Head}${infer Tail}`\n ? Head extends Upper\n ? `${Started extends true ? `_` : ``}${Lowercase<Head>}${SnakeWalk<Tail, true>}`\n : `${Head}${SnakeWalk<Tail, true>}`\n : S;\n\n/** Convert a `camelCase` string-literal type to `snake_case`. Self-contained;\n * mirrors {@link toSnakeCase} (the only transform we apply to API keys). */\ntype SnakeCase<S extends string> = SnakeWalk<S>;\n\n/**\n * Recursively snake-case the keys of an object/array type. Mirrors\n * {@link toSnakeKeys}'s runtime. Replaces type-fest's `SnakeCasedPropertiesDeep`\n * — narrower (no Set/tuple/options handling) because the only inputs are plain\n * nested Discord API JSON.\n */\nexport type SnakeKeys<T> =\n T extends ReadonlyArray<infer U>\n ? Array<SnakeKeys<U>>\n : T extends object\n ? {\n [K in keyof T as K extends string ? SnakeCase<K> : K]: SnakeKeys<\n T[K]\n >;\n }\n : T;\n\nexport const toSnakeKeys = <T extends object>(o: T): SnakeKeys<T> => {\n if (Array.isArray(o)) {\n return o.map(toSnakeKeys) as SnakeKeys<T>;\n } else if (isObject(o)) {\n return Object.entries(o).reduce((acc, [key, value]) => {\n // @ts-expect-error\n acc[toSnakeCase(key)] = toSnakeKeys(value);\n return acc;\n }, {}) as SnakeKeys<T>;\n }\n\n return o as SnakeKeys<T>;\n};\n"],"mappings":";;;AAoEA,MAAa,eAAiC,MAAuB;CACnE,IAAI,MAAM,QAAQ,CAAC,GACjB,OAAO,EAAE,IAAI,WAAW;MACnB,IAAI,SAAS,CAAC,GACnB,OAAO,OAAO,QAAQ,CAAC,EAAE,QAAQ,KAAK,CAAC,KAAK,WAAW;EAErD,IAAI,YAAY,GAAG,KAAK,YAAY,KAAK;EACzC,OAAO;CACT,GAAG,CAAC,CAAC;CAGP,OAAO;AACT"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
|
@@ -20,4 +20,5 @@ flags: Flags, /** An optional error message to display in the event an invalid v
|
|
|
20
20
|
|
|
21
21
|
message?: string) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TitleAction<string | number | bigint, TName>]>;
|
|
22
22
|
//#endregion
|
|
23
|
-
export { Flags, bitfield };
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
|
@@ -7,3 +7,5 @@ import * as v from "valibot";
|
|
|
7
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
8
|
//#endregion
|
|
9
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 @@
|
|
|
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"}
|
|
@@ -7,3 +7,5 @@ import * as v from "valibot";
|
|
|
7
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
8
|
//#endregion
|
|
9
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 @@
|
|
|
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"}
|
|
@@ -8,3 +8,5 @@ import * as v from "valibot";
|
|
|
8
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
9
|
//#endregion
|
|
10
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"}
|
|
@@ -21,4 +21,5 @@ declare const toBase64: (data: string) => string;
|
|
|
21
21
|
*/
|
|
22
22
|
declare const datauri: v.GenericSchema<string>;
|
|
23
23
|
//#endregion
|
|
24
|
-
export { datauri, datauriRegex, extractDataURIMetadata, toBase64 };
|
|
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"}
|
|
@@ -15,3 +15,5 @@ const toBase64 = (data) => typeof Buffer !== `undefined` ? Buffer.from(data, `ba
|
|
|
15
15
|
const datauri = v.pipe(v.custom((val) => typeof val === `string` && val.length > 0 && datauriRegex.test(val), `Invalid Data URI`), v.title(`datauri`));
|
|
16
16
|
//#endregion
|
|
17
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"}
|
|
@@ -126,4 +126,5 @@ declare function multipart<TEntries extends v.ObjectEntries>(entries: TEntries,
|
|
|
126
126
|
partial: true;
|
|
127
127
|
}): v.GenericSchema<v.InferOutput<v.SchemaWithPartial<v.ObjectSchema<TEntries, undefined>, undefined>>>;
|
|
128
128
|
//#endregion
|
|
129
|
-
export { FileUpload, MULTIPART_MARKER, collectFileUploads, fileUpload, isFileUpload, multipart, shouldSerializeAsMultipart, toMultipartBody };
|
|
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"}
|
|
@@ -4,8 +4,8 @@ import * as v from "valibot";
|
|
|
4
4
|
/** Type guard — true if `val` looks like a {@link FileUpload}. */
|
|
5
5
|
const isFileUpload = (val) => {
|
|
6
6
|
if (!isObject(val)) return false;
|
|
7
|
-
const
|
|
8
|
-
return typeof
|
|
7
|
+
const content = val.content;
|
|
8
|
+
return typeof val.filename === `string` && typeof content?.arrayBuffer === `function`;
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* Valibot schema for a single file upload. Validates the shape and
|
|
@@ -112,3 +112,5 @@ function multipart(entries, options) {
|
|
|
112
112
|
}
|
|
113
113
|
//#endregion
|
|
114
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"}
|
|
@@ -13,4 +13,5 @@ requirement: Array<`${string}/${string}`>, /** an optional error message on fail
|
|
|
13
13
|
|
|
14
14
|
message?: "Received badly formatted Data URI") => CheckAction<string, typeof message>;
|
|
15
15
|
//#endregion
|
|
16
|
-
export { hasMimeType };
|
|
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 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasSize.d.mts","names":[],"sources":["../../src/validations/hasSize.ts"],"mappings":";;;;cAKa,OAAA,GACX,IAAA;EAAiB,GAAA;EAAc,GAAA;AAAA,GAC/B,OAAA,wCACC,WAAW,gBAAgB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasSize.mjs","names":[],"sources":["../../src/validations/hasSize.ts"],"sourcesContent":["import type { CheckAction } from \"valibot\";\nimport { check } from \"valibot\";\nimport { extractDataURIMetadata, toBase64 } from \"./datauri.js\";\n\n/** @__NO_SIDE_EFFECTS__ */\nexport const hasSize = (\n size: number | { min?: number; max?: number },\n message = `Data URI is the incorrect size` as const\n): CheckAction<string, typeof message> =>\n check((dataURI: string) => {\n const { data } = extractDataURIMetadata(dataURI);\n\n if (typeof data === `undefined`) {\n throw new Error(`Received badly formatted Data URI`);\n }\n\n const actual = toBase64(data).length;\n return typeof size === `number`\n ? size === actual\n : actual >= (size.min ?? 0) && actual <= (size.max ?? Infinity);\n }, message);\n"],"mappings":";;;;AAKA,MAAa,WACX,MACA,UAAU,qCAEV,OAAO,YAAoB;CACzB,MAAM,EAAE,SAAS,uBAAuB,OAAO;CAE/C,IAAI,OAAO,SAAS,aAClB,MAAM,IAAI,MAAM,mCAAmC;CAGrD,MAAM,SAAS,SAAS,IAAI,EAAE;CAC9B,OAAO,OAAO,SAAS,WACnB,SAAS,SACT,WAAW,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO;AAC1D,GAAG,OAAO"}
|
|
@@ -43,7 +43,7 @@ import * as v from "valibot";
|
|
|
43
43
|
*
|
|
44
44
|
* @__NO_SIDE_EFFECTS__
|
|
45
45
|
*/
|
|
46
|
-
declare const schema: <T>(s: v.GenericSchema
|
|
46
|
+
declare const schema: <T>(s: v.GenericSchema) => v.GenericSchema<T>;
|
|
47
47
|
/**
|
|
48
48
|
* Make every key of `T` optional, both at the type level and at
|
|
49
49
|
* runtime. Equivalent to Valibot's `v.partial`, but accepts an
|
|
@@ -97,6 +97,7 @@ declare const requiredFields: <T, K extends keyof T & string>(s: v.GenericSchema
|
|
|
97
97
|
*
|
|
98
98
|
* @__NO_SIDE_EFFECTS__
|
|
99
99
|
*/
|
|
100
|
-
declare const variantSchema: <T>(key: keyof T & string, schemas:
|
|
100
|
+
declare const variantSchema: <T>(key: keyof T & string, schemas: readonly v.GenericSchema[]) => v.GenericSchema<T>;
|
|
101
101
|
//#endregion
|
|
102
|
-
export { omitFields, partialSchema, pickFields, requiredFields, schema, variantSchema };
|
|
102
|
+
export { omitFields, partialSchema, pickFields, requiredFields, schema, variantSchema };
|
|
103
|
+
//# sourceMappingURL=schema.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/validations/schema.ts"],"mappings":";;;;;AA4CA;;;;;;;;;;;;;;;;AAAgE;AAWhE;;;;;;;;;;;;;;;;;;;;AAE4B;AAc5B;;cA3Ba,MAAA,MAAa,CAAA,EAAG,CAAA,CAAE,aAAA,KAAgB,CAAA,CAAE,aAAA,CAAc,CAAA;;;;;;;;;cAWlD,aAAA,MACX,CAAA,EAAG,CAAA,CAAE,aAAA,CAAc,CAAA,MAClB,CAAA,CAAE,aAAA,CAAc,OAAA,CAAQ,CAAA;;;;;;;cAcd,UAAA,sBAAiC,CAAA,WAC5C,CAAA,EAAG,CAAA,CAAE,aAAA,CAAc,CAAA,GACnB,IAAA,WAAe,CAAA,OACd,CAAA,CAAE,aAAA,CAAc,IAAA,CAAK,CAAA,EAAG,CAAA;;;;;;;cAcd,UAAA,sBAAiC,CAAA,WAC5C,CAAA,EAAG,CAAA,CAAE,aAAA,CAAc,CAAA,GACnB,IAAA,WAAe,CAAA,OACd,CAAA,CAAE,aAAA,CAAc,IAAA,CAAK,CAAA,EAAG,CAAA;;;AAjBC;AAc5B;;;cAiBa,cAAA,sBAAqC,CAAA,WAChD,CAAA,EAAG,CAAA,CAAE,aAAA,CAAc,CAAA,GACnB,IAAA,WAAe,CAAA,OACd,CAAA,CAAE,aAAA,CAAc,CAAA,GAAI,QAAA,CAAS,IAAA,CAAK,CAAA,EAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;cA+B3B,aAAA,MACX,GAAA,QAAW,CAAA,WACX,OAAA,WAAkB,CAAA,CAAE,aAAA,OACnB,CAAA,CAAE,aAAA,CAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":[],"sources":["../../src/validations/schema.ts"],"sourcesContent":["import * as v from \"valibot\";\n\n/**\n * Annotate a schema's *published* type as `v.GenericSchema<T>` so\n * downstream `.d.ts` emit stops inlining the inner `ObjectSchema`'s\n * entries map and instead references `T` by name. The runtime value\n * is unchanged.\n *\n * Use at every type-defining schema export:\n *\n * ```ts\n * const _userSchema = v.object({...});\n * export interface User extends v.InferOutput<typeof _userSchema> {}\n * export const userSchema = schema<User>(_userSchema);\n * ```\n *\n * **Why this exists**\n *\n * Without annotation, `typeof userSchema` is the full\n * `v.ObjectSchema<{ id: v.GenericSchema<string>, ... }>` shape. Every\n * downstream file that references `userSchema` (Guild, Application,\n * Member, …) re-inlines that entries map into its own emitted\n * declarations. This causes:\n *\n * - dramatic duplication of nested object shapes in `.d.ts` output\n * - slow IDE hover (tsserver expands the full shape on every\n * reference)\n * - occasional TS2502 / type-too-complex errors on deeply circular\n * schemas (Channel, Message, …)\n *\n * After annotation, downstream `.d.ts` files reference `User` by\n * name from `./user/types/User.d.mts` and never inline its body.\n *\n * **Trade-off**\n *\n * `v.partial(userSchema)`, `v.pick(userSchema, [...])`, `v.omit(...)`,\n * and `userSchema.entries.id` stop type-checking because the constraint\n * is `ObjectSchema<...>` not `GenericSchema<T>`. Use the\n * {@link partialSchema}, {@link pickFields}, {@link omitFields},\n * {@link requiredFields}, and {@link variantSchema} helpers below for\n * the common cases.\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const schema = <T>(s: v.GenericSchema): v.GenericSchema<T> =>\n s as v.GenericSchema<T>;\n\n/**\n * Make every key of `T` optional, both at the type level and at\n * runtime. Equivalent to Valibot's `v.partial`, but accepts an\n * annotated `GenericSchema<T>` (which `v.partial` would reject because\n * its constraint is `ObjectSchema<...>`).\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const partialSchema = <T>(\n s: v.GenericSchema<T>\n): v.GenericSchema<Partial<T>> =>\n // The runtime cast is sound: schema<T>(...) returns an ObjectSchema\n // we only annotated as GenericSchema. v.partial reads from\n // ObjectSchema.entries, which is still there.\n v.partial(\n s as unknown as v.ObjectSchema<v.ObjectEntries, undefined>\n ) as unknown as v.GenericSchema<Partial<T>>;\n\n/**\n * Pick a subset of fields from `T` at both type and runtime levels.\n * Equivalent to Valibot's `v.pick`. See {@link partialSchema}.\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const pickFields = <T, K extends keyof T & string>(\n s: v.GenericSchema<T>,\n keys: readonly K[]\n): v.GenericSchema<Pick<T, K>> => {\n type Erased = v.ObjectSchema<v.ObjectEntries, undefined>;\n return v.pick(\n s as unknown as Erased,\n keys as unknown as v.ObjectKeys<Erased>\n ) as unknown as v.GenericSchema<Pick<T, K>>;\n};\n\n/**\n * Omit a subset of fields from `T` at both type and runtime levels.\n * Equivalent to Valibot's `v.omit`. See {@link partialSchema}.\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const omitFields = <T, K extends keyof T & string>(\n s: v.GenericSchema<T>,\n keys: readonly K[]\n): v.GenericSchema<Omit<T, K>> => {\n type Erased = v.ObjectSchema<v.ObjectEntries, undefined>;\n return v.omit(\n s as unknown as Erased,\n keys as unknown as v.ObjectKeys<Erased>\n ) as unknown as v.GenericSchema<Omit<T, K>>;\n};\n\n/**\n * Mark a subset of fields on `T` as required at both type and runtime\n * levels. Equivalent to Valibot's `v.required`. See {@link partialSchema}.\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const requiredFields = <T, K extends keyof T & string>(\n s: v.GenericSchema<T>,\n keys: readonly K[]\n): v.GenericSchema<T & Required<Pick<T, K>>> => {\n type Erased = v.ObjectSchema<v.ObjectEntries, undefined>;\n return v.required(\n s as unknown as Erased,\n keys as unknown as v.ObjectKeys<Erased>\n ) as unknown as v.GenericSchema<T & Required<Pick<T, K>>>;\n};\n\n/**\n * Build a discriminated union schema. Equivalent to Valibot's\n * `v.variant`, but accepts annotated `GenericSchema<T>` variants\n * (which `v.variant` would reject because its constraint is\n * `ObjectSchema<...>`).\n *\n * Prefer `v.variant` whenever variants share a literal discriminator\n * field — it dispatches on that field at runtime, producing focused\n * error messages and O(1) validation, vs. {@link v.union}'s O(n)\n * try-each behavior.\n *\n * @example\n * ```ts\n * export const channelSchema = variantSchema<Channel>(`type`, [\n * guildTextChannelSchema,\n * guildVoiceChannelSchema,\n * threadChannelSchema,\n * // ...\n * ]);\n * ```\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const variantSchema = <T>(\n key: keyof T & string,\n schemas: readonly v.GenericSchema[]\n): v.GenericSchema<T> => {\n type Erased = v.ObjectSchema<v.ObjectEntries, undefined>;\n return v.variant(\n key as never,\n schemas as unknown as [Erased, Erased, ...Erased[]]\n ) as unknown as v.GenericSchema<T>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,UAAa,MACxB;;;;;;;;;AAUF,MAAa,iBACX,MAKA,EAAE,QACA,CACF;;;;;;;AAQF,MAAa,cACX,GACA,SACgC;CAEhC,OAAO,EAAE,KACP,GACA,IACF;AACF;;;;;;;AAQA,MAAa,cACX,GACA,SACgC;CAEhC,OAAO,EAAE,KACP,GACA,IACF;AACF;;;;;;;AAQA,MAAa,kBACX,GACA,SAC8C;CAE9C,OAAO,EAAE,SACP,GACA,IACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,iBACX,KACA,YACuB;CAEvB,OAAO,EAAE,QACP,KACA,OACF;AACF"}
|
|
@@ -24,4 +24,5 @@ declare const snowflakeToDate: (/** A snowflake string to convert */val: string
|
|
|
24
24
|
*/
|
|
25
25
|
declare const snowflake: v.GenericSchema<string>;
|
|
26
26
|
//#endregion
|
|
27
|
-
export { DISCORD_EPOCH, snowflake, snowflakeToDate };
|
|
27
|
+
export { DISCORD_EPOCH, snowflake, snowflakeToDate };
|
|
28
|
+
//# sourceMappingURL=snowflake.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snowflake.d.mts","names":[],"sources":["../../src/validations/snowflake.ts"],"mappings":";;;;cAKa,aAAA;AAAb;;;;AAA0B;AAW1B;;;;AAXA,cAWa,eAAA,uCAEX,GAAA,iGAEA,KAAA,cACC,IAAsD;AAWzD;;;;AAAuC;;;;;AAAvC,cAAa,SAAA,EAAW,CAAA,CAAE,aAAa"}
|
|
@@ -26,3 +26,5 @@ const snowflakeToDate = (val, epoch = DISCORD_EPOCH) => new Date(Number((BigInt(
|
|
|
26
26
|
const snowflake = v.pipe(v.custom((val) => isNonNullable(val) && (typeof val === `bigint` || typeof val === `number` || isNumericString(val)) && snowflakeToDate(val).getTime() >= 1420070400000n, `Invalid Snowflake`), v.title(`snowflake`));
|
|
27
27
|
//#endregion
|
|
28
28
|
export { DISCORD_EPOCH, snowflake, snowflakeToDate };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=snowflake.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snowflake.mjs","names":[],"sources":["../../src/validations/snowflake.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport { isNonNullable } from \"../utils/isNonNullable.js\";\nimport { isNumericString } from \"../utils/isNumericString.js\";\n\n/** UNIX timestamp representing the first second of 2015 */\nexport const DISCORD_EPOCH = 1420070400000n;\n\n/**\n * Converts a `snowflake` string to a Date relative to the given epoch\n *\n * Uses Discord's epoch by default\n *\n * https://discord.com/developers/docs/reference#snowflakes\n *\n * @__NO_SIDE_EFFECTS__\n */\nexport const snowflakeToDate = (\n /** A snowflake string to convert */\n val: string | number | bigint,\n /** time in milliseconds to use as the epoch to derive a Date from */\n epoch = DISCORD_EPOCH\n): Date => new Date(Number((BigInt(val) >> 22n) + epoch));\n\n/**\n * An up to 64-bit unsigned numeric value derived from a timestamp which\n * serves as a unique identifier within Discord.\n *\n * Validates whether a given `number`, `bigint`, or numeric `string` is\n * a valid [Snowflake](https://discord.com/developers/docs/reference#snowflakes)\n * by checking if it's derived timestamp is a valid time at or after\n * the Discord epoch (the first second of 2015, ie: `1420070400000`).\n */\nexport const snowflake: v.GenericSchema<string> = v.pipe(\n v.custom<string, `Invalid Snowflake`>(\n (val) =>\n // at runtime this could be any value, so filter out\n // obviously invalid input first\n isNonNullable(val) &&\n // then verify we have a numeric value\n (typeof val === `bigint` ||\n typeof val === `number` ||\n isNumericString(val)) &&\n // finally, verify that it accurately represents ms\n // at or after the Discord epoch (timestamps before\n // that cannot possibly be a valid Discord snowflake)\n snowflakeToDate(val).getTime() >= DISCORD_EPOCH,\n `Invalid Snowflake`\n ),\n v.title(`snowflake`)\n);\n"],"mappings":";;;;;AAKA,MAAa,gBAAgB;;;;;;;;;;AAW7B,MAAa,mBAEX,KAEA,QAAQ,kBACC,IAAI,KAAK,QAAQ,OAAO,GAAG,KAAK,OAAO,KAAK,CAAC;;;;;;;;;;AAWxD,MAAa,YAAqC,EAAE,KAClD,EAAE,QACC,QAGC,cAAc,GAAG,MAEhB,OAAO,QAAQ,YACd,OAAO,QAAQ,YACf,gBAAgB,GAAG,MAIrB,gBAAgB,GAAG,EAAE,QAAQ,KAAA,gBAC/B,mBACF,GACA,EAAE,MAAM,WAAW,CACrB"}
|
|
@@ -4,4 +4,5 @@ import * as v from "valibot";
|
|
|
4
4
|
/** An [ISO8601](https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf) timestamp */
|
|
5
5
|
declare const timestamp: v.GenericSchema<string>;
|
|
6
6
|
//#endregion
|
|
7
|
-
export { timestamp };
|
|
7
|
+
export { timestamp };
|
|
8
|
+
//# sourceMappingURL=timestamp.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp.d.mts","names":[],"sources":["../../src/validations/timestamp.ts"],"mappings":";;;;cAGa,SAAA,EAGR,CAAA,CAAE,aAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp.mjs","names":[],"sources":["../../src/validations/timestamp.ts"],"sourcesContent":["import * as v from \"valibot\";\n\n/** An [ISO8601](https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf) timestamp */\nexport const timestamp = v.message(\n v.pipe(v.string(), v.isoTimestamp()),\n (issue) => `Expected a valid timestamp, received: ${issue.received}`\n) as v.GenericSchema<string>;\n"],"mappings":";;;AAGA,MAAa,YAAY,EAAE,QACzB,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,aAAa,CAAC,IAClC,UAAU,yCAAyC,MAAM,UAC5D"}
|