@discordkit/core 3.0.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/requests/DiscordSession.d.ts +9 -0
  2. package/dist/requests/DiscordSession.js +213 -0
  3. package/dist/requests/DiscordSession.js.map +1 -1
  4. package/dist/requests/index.d.ts +1 -0
  5. package/dist/requests/index.js +1 -0
  6. package/dist/requests/index.js.map +1 -1
  7. package/dist/requests/request.js +5 -10
  8. package/dist/requests/request.js.map +1 -1
  9. package/dist/requests/toProcedure.d.ts +8 -8
  10. package/dist/requests/toProcedure.js +24 -14
  11. package/dist/requests/toProcedure.js.map +1 -1
  12. package/dist/requests/verifyKey.d.ts +10 -0
  13. package/dist/requests/verifyKey.js +91 -0
  14. package/dist/requests/verifyKey.js.map +1 -0
  15. package/dist/utils/isBetween.d.ts +1 -0
  16. package/dist/utils/isBetween.js +2 -0
  17. package/dist/utils/isBetween.js.map +1 -0
  18. package/dist/utils/isNumericString.d.ts +1 -0
  19. package/dist/utils/isNumericString.js +2 -0
  20. package/dist/utils/isNumericString.js.map +1 -0
  21. package/dist/utils/sleep.d.ts +4 -0
  22. package/dist/utils/sleep.js +5 -0
  23. package/dist/utils/sleep.js.map +1 -0
  24. package/dist/validations/asDigits.d.ts +5 -2
  25. package/dist/validations/asDigits.js +5 -2
  26. package/dist/validations/asDigits.js.map +1 -1
  27. package/dist/validations/asInteger.d.ts +5 -2
  28. package/dist/validations/asInteger.js +5 -2
  29. package/dist/validations/asInteger.js.map +1 -1
  30. package/dist/validations/bitfield.d.ts +13 -1
  31. package/dist/validations/bitfield.js +15 -2
  32. package/dist/validations/bitfield.js.map +1 -1
  33. package/dist/validations/boundedArray.d.ts +6 -0
  34. package/dist/validations/boundedArray.js +8 -0
  35. package/dist/validations/boundedArray.js.map +1 -0
  36. package/dist/validations/boundedInteger.d.ts +6 -0
  37. package/dist/validations/boundedInteger.js +8 -0
  38. package/dist/validations/boundedInteger.js.map +1 -0
  39. package/dist/validations/boundedString.d.ts +6 -0
  40. package/dist/validations/boundedString.js +8 -0
  41. package/dist/validations/boundedString.js.map +1 -0
  42. package/dist/validations/datauri.d.ts +2 -1
  43. package/dist/validations/datauri.js +2 -2
  44. package/dist/validations/datauri.js.map +1 -1
  45. package/dist/validations/index.d.ts +5 -0
  46. package/dist/validations/index.js +5 -0
  47. package/dist/validations/index.js.map +1 -1
  48. package/dist/validations/snowflake.d.ts +10 -11
  49. package/dist/validations/snowflake.js +21 -16
  50. package/dist/validations/snowflake.js.map +1 -1
  51. package/dist/validations/timestamp.d.ts +3 -0
  52. package/dist/validations/timestamp.js +4 -0
  53. package/dist/validations/timestamp.js.map +1 -0
  54. package/dist/validations/url.d.ts +2 -0
  55. package/dist/validations/url.js +3 -0
  56. package/dist/validations/url.js.map +1 -0
  57. package/package.json +1 -1
@@ -3,6 +3,7 @@ export declare const endpoint = "https://discord.com/api/v10/";
3
3
  export declare class DiscordSession {
4
4
  #private;
5
5
  endpoint: string;
6
+ maxRetries: number;
6
7
  get ready(): boolean;
7
8
  constructor(authToken?: `${`Bot` | `Bearer`} ${string}` | null);
8
9
  /**
@@ -12,5 +13,13 @@ export declare class DiscordSession {
12
13
  setToken: (token: `${`Bot` | `Bearer`} ${string}`) => this;
13
14
  clearSession: () => this;
14
15
  getSession: () => string;
16
+ /**
17
+ * Queue a request to be processed with rate limiting
18
+ */
19
+ queueRequest: (resource: URL, method: string, body?: string | null) => Promise<Response>;
20
+ /**
21
+ * Get current queue size (useful for monitoring)
22
+ */
23
+ getQueueSize: () => number;
15
24
  }
16
25
  export declare const discord: DiscordSession;
@@ -1,8 +1,26 @@
1
+ import { sleep } from "../utils/sleep.js";
1
2
  export const endpoint = `https://discord.com/api/v10/`;
2
3
  /** @internal */
3
4
  export class DiscordSession {
4
5
  endpoint = endpoint;
6
+ maxRetries = 5;
5
7
  #authToken = null;
8
+ // Rate limit tracking
9
+ #buckets = new Map();
10
+ #globalReset = 0; // Epoch timestamp when global limit resets
11
+ #requestQueue = [];
12
+ #processingQueue = false;
13
+ // Global rate limit: 50 requests per second
14
+ #globalLimit = 50;
15
+ #globalWindow = 1000; // 1 second in ms
16
+ #globalRequestTimestamps = [];
17
+ // Invalid request tracking: 10,000 per 10 minutes
18
+ #invalidRequests = {
19
+ count: 0,
20
+ windowStart: Date.now()
21
+ };
22
+ #invalidRequestLimit = 10000;
23
+ #invalidRequestWindow = 10 * 60 * 1000; // 10 minutes in ms
6
24
  get ready() {
7
25
  return Boolean(this.#authToken);
8
26
  }
@@ -28,6 +46,14 @@ export class DiscordSession {
28
46
  };
29
47
  clearSession = () => {
30
48
  this.#authToken = null;
49
+ this.#buckets.clear();
50
+ this.#globalReset = 0;
51
+ this.#requestQueue = [];
52
+ this.#globalRequestTimestamps = [];
53
+ this.#invalidRequests = {
54
+ count: 0,
55
+ windowStart: Date.now()
56
+ };
31
57
  return this;
32
58
  };
33
59
  getSession = () => {
@@ -37,6 +63,193 @@ export class DiscordSession {
37
63
  }
38
64
  return token;
39
65
  };
66
+ /**
67
+ * Queue a request to be processed with rate limiting
68
+ */
69
+ queueRequest = async (resource, method, body) => {
70
+ return new Promise((resolve, reject) => {
71
+ this.#requestQueue.push({
72
+ resource,
73
+ method,
74
+ body,
75
+ resolve,
76
+ reject
77
+ });
78
+ // Start processing if not already running
79
+ void this.#processQueue(); // This will return early if already processing
80
+ });
81
+ };
82
+ /**
83
+ * Process the request queue with rate limiting
84
+ */
85
+ #processQueue = async () => {
86
+ if (this.#processingQueue)
87
+ return;
88
+ this.#processingQueue = true;
89
+ while (this.#requestQueue.length > 0) {
90
+ const now = Date.now();
91
+ // Check if we're temporarily banned (invalid request limit)
92
+ if (this.#isTemporarilyBanned()) {
93
+ const waitTime = this.#invalidRequestWindow -
94
+ (now - this.#invalidRequests.windowStart);
95
+ console.warn(`Temporarily banned from Discord API. Waiting ${Math.ceil(waitTime / 1000)}s`);
96
+ await sleep(waitTime);
97
+ this.#resetInvalidRequestCounter();
98
+ }
99
+ // Check global rate limit (50 req/s)
100
+ await this.#enforceGlobalRateLimit();
101
+ // Check if we're under a global rate limit cooldown
102
+ if (this.#globalReset > now / 1000) {
103
+ const waitTime = (this.#globalReset - now / 1000) * 1000;
104
+ await sleep(waitTime);
105
+ continue;
106
+ }
107
+ const request = this.#requestQueue[0];
108
+ if (typeof request === `undefined`)
109
+ break;
110
+ const bucket = this.#buckets.get(`${request.method}:${request.resource}`);
111
+ if (bucket?.remaining === 0) {
112
+ const resetTime = bucket.reset * 1000; // Convert to ms
113
+ if (resetTime > now) {
114
+ await sleep(resetTime - now);
115
+ }
116
+ }
117
+ // Execute the request
118
+ this.#requestQueue.shift();
119
+ try {
120
+ const response = await this.#executeRequest(request);
121
+ request.resolve(response);
122
+ }
123
+ catch (error) {
124
+ if (error instanceof Error) {
125
+ request.reject(error);
126
+ }
127
+ }
128
+ }
129
+ this.#processingQueue = false;
130
+ // Check if any requests were added while we were processing the last one
131
+ if (this.#requestQueue.length > 0) {
132
+ void this.#processQueue(); // Restart the processor
133
+ }
134
+ };
135
+ /**
136
+ * Execute a single request and handle rate limit headers
137
+ */
138
+ #executeRequest = async (request, retryCount = 0) => {
139
+ const token = this.getSession();
140
+ const now = Date.now();
141
+ // Track this request for global rate limiting
142
+ this.#globalRequestTimestamps.push(now);
143
+ const headers = {
144
+ Authorization: token
145
+ };
146
+ if (request.body) {
147
+ headers[`Content-Type`] = `application/json`;
148
+ }
149
+ const response = await fetch(request.resource.toString(), {
150
+ method: request.method,
151
+ body: request.body,
152
+ headers
153
+ });
154
+ // Update rate limit tracking from headers
155
+ this.#updateRateLimits(response);
156
+ // Handle 429 Too Many Requests
157
+ if (response.status === 429) {
158
+ if (retryCount >= this.maxRetries) {
159
+ console.error(`Max retries (${this.maxRetries}) exceeded for ${request.resource}`);
160
+ return response; // Return the 429 response instead of retrying forever
161
+ }
162
+ const retryAfter = response.headers.get(`Retry-After`) ?? `1`;
163
+ const isGlobal = response.headers.get(`X-RateLimit-Global`) === `true`;
164
+ const scope = response.headers.get(`X-RateLimit-Scope`);
165
+ if (isGlobal || scope === `global`) {
166
+ console.warn(`Hit global rate limit`);
167
+ this.#globalReset = now / 1000 + parseFloat(retryAfter);
168
+ }
169
+ // Wait before retrying
170
+ await sleep(parseFloat(retryAfter) * 1000);
171
+ // Retry with incremented counter
172
+ return this.#executeRequest(request, retryCount + 1);
173
+ }
174
+ // Track invalid requests (401, 403, 429 excluding shared scope)
175
+ if ([401, 403].includes(response.status) ||
176
+ (response.status === 429 &&
177
+ response.headers.get(`X-RateLimit-Scope`) !== `shared`)) {
178
+ this.#trackInvalidRequest();
179
+ }
180
+ return response;
181
+ };
182
+ /**
183
+ * Update rate limit buckets from response headers
184
+ */
185
+ #updateRateLimits = (response) => {
186
+ const bucket = response.headers.get(`X-RateLimit-Bucket`);
187
+ const limit = response.headers.get(`X-RateLimit-Limit`);
188
+ const remaining = response.headers.get(`X-RateLimit-Remaining`);
189
+ const reset = response.headers.get(`X-RateLimit-Reset`);
190
+ const resetAfter = response.headers.get(`X-RateLimit-Reset-After`);
191
+ if (bucket && limit && remaining && reset && resetAfter) {
192
+ this.#buckets.set(bucket, {
193
+ limit: parseInt(limit, 10),
194
+ remaining: parseInt(remaining, 10),
195
+ reset: parseFloat(reset),
196
+ resetAfter: parseFloat(resetAfter)
197
+ });
198
+ }
199
+ };
200
+ /**
201
+ * Enforce global rate limit of 50 requests per second
202
+ */
203
+ #enforceGlobalRateLimit = async () => {
204
+ const now = Date.now();
205
+ // Remove timestamps older than 1 second
206
+ this.#globalRequestTimestamps = this.#globalRequestTimestamps.filter((timestamp) => now - timestamp < this.#globalWindow);
207
+ // If we're at the limit, wait
208
+ if (this.#globalRequestTimestamps.length >= this.#globalLimit) {
209
+ const oldestTimestamp = this.#globalRequestTimestamps[0];
210
+ const waitTime = this.#globalWindow - (now - oldestTimestamp);
211
+ if (waitTime > 0) {
212
+ await sleep(waitTime);
213
+ }
214
+ }
215
+ };
216
+ /**
217
+ * Track invalid requests for Cloudflare ban prevention
218
+ */
219
+ #trackInvalidRequest = () => {
220
+ const now = Date.now();
221
+ // Reset counter if window has passed
222
+ if (now - this.#invalidRequests.windowStart >= this.#invalidRequestWindow) {
223
+ this.#resetInvalidRequestCounter();
224
+ }
225
+ this.#invalidRequests.count++;
226
+ if (this.#invalidRequests.count >= this.#invalidRequestLimit) {
227
+ console.error(`Approaching invalid request limit! Bot may be temporarily banned.`);
228
+ }
229
+ };
230
+ /**
231
+ * Check if we're temporarily banned
232
+ */
233
+ #isTemporarilyBanned = () => {
234
+ const now = Date.now();
235
+ if (now - this.#invalidRequests.windowStart < this.#invalidRequestWindow) {
236
+ return this.#invalidRequests.count >= this.#invalidRequestLimit;
237
+ }
238
+ return false;
239
+ };
240
+ /**
241
+ * Reset invalid request counter
242
+ */
243
+ #resetInvalidRequestCounter = () => {
244
+ this.#invalidRequests = {
245
+ count: 0,
246
+ windowStart: Date.now()
247
+ };
248
+ };
249
+ /**
250
+ * Get current queue size (useful for monitoring)
251
+ */
252
+ getQueueSize = () => this.#requestQueue.length;
40
253
  }
41
254
  export const discord = new DiscordSession();
42
255
  //# sourceMappingURL=DiscordSession.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiscordSession.js","sourceRoot":"","sources":["../../src/requests/DiscordSession.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAEvD,gBAAgB;AAChB,MAAM,OAAO,cAAc;IACzB,QAAQ,GAAW,QAAQ,CAAC;IAC5B,UAAU,GAAkB,IAAI,CAAC;IACjC,IAAI,KAAK;QACP,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,YAAY,SAAkD;QAC5D,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,QAAQ,GAAG,CAAC,KAAsC,EAAQ,EAAE;QAC1D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,+DAA+D,KAAK,EAAE,CACvE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,YAAY,GAAG,GAAS,EAAE;QACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,UAAU,GAAG,GAAW,EAAE;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;QAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;CACH;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"DiscordSession.js","sourceRoot":"","sources":["../../src/requests/DiscordSession.ts"],"names":[],"mappings":"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"}
@@ -5,3 +5,4 @@ export * from "./methods.js";
5
5
  export * from "./toProcedure.js";
6
6
  export * from "./toQuery.js";
7
7
  export * from "./toValidated.js";
8
+ export * from "./verifyKey.js";
@@ -5,4 +5,5 @@ export * from "./methods.js";
5
5
  export * from "./toProcedure.js";
6
6
  export * from "./toQuery.js";
7
7
  export * from "./toValidated.js";
8
+ export * from "./verifyKey.js";
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/requests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/requests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
@@ -8,20 +8,15 @@ export const request = async (resource, method = `GET`, body) => {
8
8
  }
9
9
  const json = () => {
10
10
  try {
11
- return body ? JSON.stringify(toSnakeKeys(body)) : body; //?
11
+ return body ? JSON.stringify(toSnakeKeys(body)) : body;
12
12
  }
13
- catch (err) {
13
+ catch (cause) {
14
14
  console.error(`Received malformed request body:\n\n`, { body });
15
- throw new Error(`Failed to stringify request body!`, err);
15
+ throw new Error(`Failed to stringify request body!`, { cause });
16
16
  }
17
17
  };
18
- const res = await fetch(resource.toString(), {
19
- method,
20
- body: json(),
21
- headers: {
22
- Authorization: token
23
- }
24
- });
18
+ // Queue the request through the rate limiter
19
+ const res = await discord.queueRequest(resource, method, json());
25
20
  if (!res.ok) {
26
21
  throw new Error(`Request to resource '${resource.toString()}' failed:\n\n${res.statusText}`);
27
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/requests/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,QAAa,EACb,MAAM,GAAG,KAAK,EACd,IAAkB,EACN,EAAE;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,GAA8B,EAAE;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG;QAC7D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE;QAC3C,MAAM;QACN,IAAI,EAAE,IAAI,EAAE;QACZ,OAAO,EAAE;YACP,aAAa,EAAE,KAAK;SACrB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,CAAC,QAAQ,EAAE,gBACzC,GAAG,CAAC,UACN,EAAE,CACH,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,mBAAmB;QACnB,OAAO;IACT,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC,CAAC"}
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/requests/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,QAAa,EACb,MAAM,GAAG,KAAK,EACd,IAAkB,EACN,EAAE;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,GAA8B,EAAE;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC;IAEF,6CAA6C;IAC7C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,CAAC,QAAQ,EAAE,gBACzC,GAAG,CAAC,UACN,EAAE,CACH,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,mBAAmB;QACnB,OAAO;IACT,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC,CAAC"}
@@ -1,19 +1,19 @@
1
- import type { GenericSchema, GenericSchemaAsync, InferInput, InferOutput } from "valibot";
1
+ import type * as v from "valibot";
2
2
  import type { AnyProcedureBuilder, MutationProcedure, ProcedureType, QueryProcedure, SubscriptionProcedure } from "@trpc/server/unstable-core-do-not-import";
3
3
  import type { Fetcher } from "./methods.js";
4
- type Result<T = void> = T extends GenericSchema | GenericSchemaAsync ? InferOutput<T> : T;
5
- type Schema = GenericSchema | GenericSchemaAsync;
4
+ type Result<T = void> = T extends v.GenericSchema | v.GenericSchemaAsync ? v.InferOutput<T> : T;
5
+ type Schema = v.GenericSchema | v.GenericSchemaAsync;
6
6
  type ProvedureDef<I extends Schema | null = null, O extends Schema | null = null> = I extends Schema ? O extends Schema ? {
7
- input: InferInput<I>;
8
- output: InferOutput<O>;
7
+ input: v.InferInput<I>;
8
+ output: v.InferOutput<O>;
9
9
  meta: unknown;
10
10
  } : {
11
- input: InferInput<I>;
11
+ input: v.InferInput<I>;
12
12
  output: undefined;
13
13
  meta: unknown;
14
14
  } : O extends Schema ? {
15
15
  input: undefined;
16
- output: InferOutput<O>;
16
+ output: v.InferOutput<O>;
17
17
  meta: unknown;
18
18
  } : {
19
19
  input: undefined;
@@ -27,5 +27,5 @@ type BaseProcedure<T extends ProcedureType, I extends Schema | null = null, O ex
27
27
  * builder of the given procedure type. This can then be used in a tRPC router
28
28
  * to scaffold an API route to forward a request to Discord's API.
29
29
  */
30
- export declare const toProcedure: <T extends ProcedureType, I extends GenericSchema | GenericSchemaAsync | null = null, O extends GenericSchema | GenericSchemaAsync | null = null>(type: T, fn: Fetcher<I extends GenericSchema | GenericSchemaAsync ? I : null, Result<O>>, input?: I, output?: O) => (procedure: AnyProcedureBuilder) => BaseProcedure<T, I, O>;
30
+ export declare const toProcedure: <T extends ProcedureType, I extends Schema | null = null, O extends Schema | null = null>(type: T, fn: Fetcher<I extends Schema ? I : null, Result<O>>, input?: I, output?: O) => (procedure: AnyProcedureBuilder, errorHandler?: (error: unknown) => void) => BaseProcedure<T, I, O>;
31
31
  export {};
@@ -5,22 +5,32 @@ import { isNonNullable } from "../utils/isNonNullable.js";
5
5
  * builder of the given procedure type. This can then be used in a tRPC router
6
6
  * to scaffold an API route to forward a request to Discord's API.
7
7
  */
8
- export const toProcedure = (type, fn, input, output) => (procedure) => {
9
- if (isNonNullable(input) && isNonNullable(output)) {
8
+ export const toProcedure = (type, fn, input, output) => (procedure, errorHandler) => {
9
+ try {
10
+ if (isNonNullable(input) && isNonNullable(output)) {
11
+ // @ts-expect-error
12
+ return procedure
13
+ .input(input)
14
+ .output(output)[type](async (opts) => fn(opts.input));
15
+ }
16
+ if (isNonNullable(input) && !isNonNullable(output)) {
17
+ // @ts-expect-error
18
+ return procedure.input(input)[type](async (opts) => fn(opts.input));
19
+ }
20
+ if (!isNonNullable(input) && isNonNullable(output)) {
21
+ // @ts-expect-error
22
+ return procedure.output(output)[type](async () => fn());
23
+ }
10
24
  // @ts-expect-error
11
- return procedure
12
- .input(input)
13
- .output(output)[type](async (opts) => fn(opts.input));
25
+ return procedure[type](async () => fn());
14
26
  }
15
- if (isNonNullable(input) && !isNonNullable(output)) {
16
- // @ts-expect-error
17
- return procedure.input(input)[type](async (opts) => fn(opts.input));
18
- }
19
- if (!isNonNullable(input) && isNonNullable(output)) {
20
- // @ts-expect-error
21
- return procedure.output(output)[type](async () => fn());
27
+ catch (error) {
28
+ if (typeof errorHandler === `function`) {
29
+ errorHandler(error);
30
+ }
31
+ throw new Error(`Unhandled Procedure Error!`, {
32
+ cause: error
33
+ });
22
34
  }
23
- // @ts-expect-error
24
- return procedure[type](async () => fn());
25
35
  };
26
36
  //# sourceMappingURL=toProcedure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toProcedure.js","sourceRoot":"","sources":["../../src/requests/toProcedure.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAsC1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,CAKE,IAAO,EACP,EAGC,EACD,KAAS,EACT,MAAU,EACV,EAAE,CACJ,CAAC,SAA8B,EAA0B,EAAE;IACzD,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,mBAAmB;QACnB,OAAO,SAAS;aACb,KAAK,CAAC,KAAK,CAAC;aACZ,MAAM,CAAC,MAAM,CAAC,CACd,IAAI,CAAC,CAAC,KAAK,EAAE,IAAwB,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,mBAAmB;QACnB,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,mBAAmB;QACnB,OAAO,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,mBAAmB;IACnB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC,CAAC"}
1
+ {"version":3,"file":"toProcedure.js","sourceRoot":"","sources":["../../src/requests/toProcedure.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAsC1D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,CAKE,IAAO,EACP,EAAmD,EACnD,KAAS,EACT,MAAU,EACV,EAAE,CACJ,CACE,SAA8B,EAC9B,YAAuC,EACf,EAAE;IAC1B,IAAI,CAAC;QACH,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,mBAAmB;YACnB,OAAO,SAAS;iBACb,KAAK,CAAC,KAAK,CAAC;iBACZ,MAAM,CAAC,MAAM,CAAC,CACd,IAAI,CAAC,CAAC,KAAK,EAAE,IAAwB,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,mBAAmB;YACnB,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,mBAAmB;YACnB,OAAO,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,mBAAmB;QACnB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;YACvC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE;YAC5C,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validates a payload from Discord against its signature and key.
3
+ *
4
+ * @param rawBody - The raw payload data
5
+ * @param signature - The signature from the `X-Signature-Ed25519` header
6
+ * @param timestamp - The timestamp from the `X-Signature-Timestamp` header
7
+ * @param clientPublicKey - The public key from the Discord developer dashboard
8
+ * @returns Whether or not validation was successful
9
+ */
10
+ export declare function verifyKey(rawBody: Uint8Array | ArrayBuffer | Buffer | string, signature: string, timestamp: string, clientPublicKey: string | CryptoKey): Promise<boolean>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Get the SubtleCrypto interface for the current environment
3
+ */
4
+ const getSubtleCrypto = () => {
5
+ // Node.js environment
6
+ if (typeof globalThis.crypto !== `undefined`) {
7
+ return globalThis.crypto.subtle;
8
+ }
9
+ // Older Node.js versions
10
+ if (typeof global !== `undefined` && global.crypto?.subtle) {
11
+ return global.crypto.subtle;
12
+ }
13
+ // Browser environment
14
+ if (typeof window !== `undefined` && window.crypto?.subtle) {
15
+ return window.crypto.subtle;
16
+ }
17
+ throw new Error(`SubtleCrypto is not available in this environment`);
18
+ };
19
+ const subtleCrypto = getSubtleCrypto();
20
+ /**
21
+ * Convert various input types to Uint8Array
22
+ */
23
+ function valueToUint8Array(value, encoding) {
24
+ // Already a Uint8Array
25
+ if (value instanceof Uint8Array) {
26
+ return value;
27
+ }
28
+ // ArrayBuffer
29
+ if (value instanceof ArrayBuffer) {
30
+ return new Uint8Array(value);
31
+ }
32
+ // Buffer (Node.js)
33
+ if (typeof Buffer !== `undefined` && Buffer.isBuffer(value)) {
34
+ return new Uint8Array(value);
35
+ }
36
+ // String
37
+ if (typeof value === `string`) {
38
+ if (encoding === `hex`) {
39
+ // Convert hex string to Uint8Array
40
+ const matches = value.match(/.{1,2}/g);
41
+ if (!matches) {
42
+ throw new Error(`Invalid hex string`);
43
+ }
44
+ return new Uint8Array(matches.map((byte) => parseInt(byte, 16)));
45
+ }
46
+ // Default to UTF-8 encoding
47
+ const encoder = new TextEncoder();
48
+ return encoder.encode(value);
49
+ }
50
+ throw new Error(`Unsupported value type`);
51
+ }
52
+ /**
53
+ * Concatenate multiple Uint8Arrays into a single Uint8Array
54
+ */
55
+ function concatUint8Arrays(...arrays) {
56
+ const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
57
+ const result = new Uint8Array(totalLength);
58
+ let offset = 0;
59
+ for (const arr of arrays) {
60
+ result.set(arr, offset);
61
+ offset += arr.length;
62
+ }
63
+ return result;
64
+ }
65
+ /**
66
+ * Validates a payload from Discord against its signature and key.
67
+ *
68
+ * @param rawBody - The raw payload data
69
+ * @param signature - The signature from the `X-Signature-Ed25519` header
70
+ * @param timestamp - The timestamp from the `X-Signature-Timestamp` header
71
+ * @param clientPublicKey - The public key from the Discord developer dashboard
72
+ * @returns Whether or not validation was successful
73
+ */
74
+ export async function verifyKey(rawBody, signature, timestamp, clientPublicKey) {
75
+ try {
76
+ return await subtleCrypto.verify({
77
+ name: `ed25519`
78
+ }, typeof clientPublicKey === `string`
79
+ ? await subtleCrypto.importKey(`raw`, Buffer.from(valueToUint8Array(clientPublicKey, `hex`)), {
80
+ name: `ed25519`,
81
+ namedCurve: `ed25519`
82
+ }, // Type assertion for Ed25519
83
+ false, [`verify`])
84
+ : clientPublicKey, Buffer.from(valueToUint8Array(signature, `hex`)), Buffer.from(concatUint8Arrays(valueToUint8Array(timestamp), valueToUint8Array(rawBody))));
85
+ }
86
+ catch (err) {
87
+ console.error(`Signature verification failed:`, err);
88
+ return false;
89
+ }
90
+ }
91
+ //# sourceMappingURL=verifyKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyKey.js","sourceRoot":"","sources":["../../src/requests/verifyKey.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const isBetween: (val: number, min: number, max: number) => boolean;
@@ -0,0 +1,2 @@
1
+ export const isBetween = (val, min, max) => val >= min && val <= max;
2
+ //# sourceMappingURL=isBetween.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isBetween.js","sourceRoot":"","sources":["../../src/utils/isBetween.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,GAAW,EAAW,EAAE,CAC1E,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const isNumericString: (val: unknown) => val is string;
@@ -0,0 +1,2 @@
1
+ export const isNumericString = (val) => typeof val === `string` && /^\d+$/.test(val);
2
+ //# sourceMappingURL=isNumericString.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isNumericString.js","sourceRoot":"","sources":["../../src/utils/isNumericString.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAY,EAAiB,EAAE,CAC7D,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Sleep for a given number of milliseconds
3
+ */
4
+ export declare const sleep: (ms: number) => Promise<void>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Sleep for a given number of milliseconds
3
+ */
4
+ export const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
5
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../src/utils/sleep.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAU,EAAiB,EAAE,CACvD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC"}
@@ -1,3 +1,6 @@
1
- import type { CustomSchema, DigitsAction, SchemaWithPipe, TransformAction } from "valibot";
1
+ import * as v from "valibot";
2
2
  import type { bitfield } from "./bitfield.js";
3
- export declare const asDigits: (schema: ReturnType<typeof bitfield>) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TransformAction<string | number | bigint, string>, DigitsAction<string, undefined>]>;
3
+ /**
4
+ * Transforms a `bitfield` schema into a numeric string
5
+ */
6
+ export declare const asDigits: (schema: ReturnType<typeof bitfield>) => v.GenericSchema<string>;
@@ -1,3 +1,6 @@
1
- import { digits, pipe, transform } from "valibot";
2
- export const asDigits = (schema) => pipe(schema, transform((val) => val.toString()), digits());
1
+ import * as v from "valibot";
2
+ /**
3
+ * Transforms a `bitfield` schema into a numeric string
4
+ */
5
+ export const asDigits = (schema) => v.pipe(schema, v.transform((val) => val.toString()), v.digits());
3
6
  //# sourceMappingURL=asDigits.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asDigits.js","sourceRoot":"","sources":["../../src/validations/asDigits.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGlD,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,MAAmC,EAOnC,EAAE,CACF,IAAI,CACF,MAAM,EACN,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAClC,MAAM,EAAE,CACT,CAAC"}
1
+ {"version":3,"file":"asDigits.js","sourceRoot":"","sources":["../../src/validations/asDigits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAG7B;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,MAAmC,EACV,EAAE,CAC3B,CAAC,CAAC,IAAI,CACJ,MAAM,EACN,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EACpC,CAAC,CAAC,MAAM,EAAE,CACgB,CAAC"}
@@ -1,3 +1,6 @@
1
- import type { CustomSchema, IntegerAction, SchemaWithPipe, TransformAction } from "valibot";
1
+ import * as v from "valibot";
2
2
  import type { bitfield } from "./bitfield.js";
3
- export declare const asInteger: (schema: ReturnType<typeof bitfield>) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TransformAction<string | number | bigint, number>, IntegerAction<number, undefined>]>;
3
+ /**
4
+ * Transforms a `bitfield` schema into an integer
5
+ */
6
+ export declare const asInteger: (schema: ReturnType<typeof bitfield>) => v.GenericSchema<number>;
@@ -1,3 +1,6 @@
1
- import { integer, pipe, transform } from "valibot";
2
- export const asInteger = (schema) => pipe(schema, transform((val) => parseInt(val.toString(), 10)), integer());
1
+ import * as v from "valibot";
2
+ /**
3
+ * Transforms a `bitfield` schema into an integer
4
+ */
5
+ export const asInteger = (schema) => v.pipe(schema, v.transform((val) => parseInt(val.toString(), 10)), v.integer());
3
6
  //# sourceMappingURL=asInteger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asInteger.js","sourceRoot":"","sources":["../../src/validations/asInteger.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGnD,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,MAAmC,EAOnC,EAAE,CACF,IAAI,CACF,MAAM,EACN,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAChD,OAAO,EAAE,CACV,CAAC"}
1
+ {"version":3,"file":"asInteger.js","sourceRoot":"","sources":["../../src/validations/asInteger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAG7B;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,MAAmC,EACV,EAAE,CAC3B,CAAC,CAAC,IAAI,CACJ,MAAM,EACN,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAClD,CAAC,CAAC,OAAO,EAAE,CACe,CAAC"}
@@ -2,4 +2,16 @@ import { type SchemaWithPipe, type TitleAction, type CustomSchema } from "valibo
2
2
  export interface Flags {
3
3
  [key: string]: number | bigint | string;
4
4
  }
5
- export declare const bitfield: <TName extends string>(name: TName, flags: Flags, message?: string) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TitleAction<string | number | bigint, TName>]>;
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
+ export declare const bitfield: <TName extends string>(
12
+ /** A name to differentiate this custom schema */
13
+ name: TName,
14
+ /** An enum of bitwise flags */
15
+ flags: Flags,
16
+ /** An optional error message to display in the event an invalid value is parsed */
17
+ message?: string) => SchemaWithPipe<readonly [CustomSchema<string | number | bigint, string>, TitleAction<string | number | bigint, TName>]>;
@@ -1,6 +1,19 @@
1
1
  import { custom, pipe, title } from "valibot";
2
2
  import { isNonNullable } from "../utils/isNonNullable.js";
3
- export const bitfield = (name, flags, message = `Invalid Bitfield`) => {
3
+ import { isNumericString } from "../utils/isNumericString.js";
4
+ /**
5
+ * Given an enum of bitwise flags, creates a new schema that
6
+ * can validate a [bitfield](https://en.wikipedia.org/wiki/Bit_field)
7
+ * numeric value (a data structure for efficiently serializing a
8
+ * group of boolean values).
9
+ */
10
+ export const bitfield = (
11
+ /** A name to differentiate this custom schema */
12
+ name,
13
+ /** An enum of bitwise flags */
14
+ flags,
15
+ /** An optional error message to display in the event an invalid value is parsed */
16
+ message = `Invalid Bitfield`) => {
4
17
  // because enums are bidirectionally indexed, pick only the numerical values
5
18
  const flagValues = Object.values(flags).filter(
6
19
  // flag enums have numerical values, so remove all the key name strings
@@ -16,7 +29,7 @@ export const bitfield = (name, flags, message = `Invalid Bitfield`) => {
16
29
  // only work on supported types
17
30
  (typeof val === `number` ||
18
31
  typeof val === `bigint` ||
19
- typeof val === `string`)
32
+ isNumericString(val))
20
33
  ? // validate the value against the given flags
21
34
  (BigInt(val) & mask) === BigInt(val)
22
35
  : false, message), title(name));
@@ -1 +1 @@
1
- {"version":3,"file":"bitfield.js","sourceRoot":"","sources":["../../src/validations/bitfield.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,IAAI,EACJ,KAAK,EAIN,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM1D,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAW,EACX,KAAY,EACZ,UAAkB,kBAAkB,EAMpC,EAAE;IACF,4EAA4E;IAC5E,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM;IAC5C,uEAAuE;IACvE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAC/B,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,gDAAgD;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAC5B,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EACrC,EAAE,CACH,CAAC;IACF,OAAO,IAAI,CACT,MAAM,CACJ,CAAC,GAAG,EAAE,EAAE;IACN,oCAAoC;IACpC,aAAa,CAAC,GAAG,CAAC;QAClB,+BAA+B;QAC/B,CAAC,OAAO,GAAG,KAAK,QAAQ;YACtB,OAAO,GAAG,KAAK,QAAQ;YACvB,OAAO,GAAG,KAAK,QAAQ,CAAC;QACxB,CAAC,CAAC,6CAA6C;YAC7C,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC;QACtC,CAAC,CAAC,KAAK,EACX,OAAO,CACR,EACD,KAAK,CAAC,IAAI,CAAC,CACZ,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"bitfield.js","sourceRoot":"","sources":["../../src/validations/bitfield.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,IAAI,EACJ,KAAK,EAIN,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAM9D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;AACtB,iDAAiD;AACjD,IAAW;AACX,+BAA+B;AAC/B,KAAY;AACZ,mFAAmF;AACnF,UAAkB,kBAAkB,EAMpC,EAAE;IACF,4EAA4E;IAC5E,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM;IAC5C,uEAAuE;IACvE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAC/B,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,gDAAgD;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAC5B,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EACrC,EAAE,CACH,CAAC;IACF,OAAO,IAAI,CACT,MAAM,CACJ,CAAC,GAAG,EAAE,EAAE;IACN,oCAAoC;IACpC,aAAa,CAAC,GAAG,CAAC;QAClB,+BAA+B;QAC/B,CAAC,OAAO,GAAG,KAAK,QAAQ;YACtB,OAAO,GAAG,KAAK,QAAQ;YACvB,eAAe,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC,CAAC,6CAA6C;YAC7C,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC;QACtC,CAAC,CAAC,KAAK,EACX,OAAO,CACR,EACD,KAAK,CAAC,IAAI,CAAC,CACZ,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import * as v from "valibot";
2
+ /** A non-empty array with a length within the given bounds */
3
+ export declare const boundedArray: <TItem>(items: v.GenericSchema<TItem>, req?: number | {
4
+ min?: number;
5
+ max?: number;
6
+ }) => v.GenericSchema<TItem[]>;
@@ -0,0 +1,8 @@
1
+ import * as v from "valibot";
2
+ /** A non-empty array with a length within the given bounds */
3
+ export const boundedArray = (items, req = {}) => v.message(typeof req === `number`
4
+ ? v.pipe(v.array(items), v.length(req))
5
+ : typeof req.max === `number`
6
+ ? v.pipe(v.array(items), v.minLength(req.min ?? 1), v.maxLength(req.max))
7
+ : 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
+ //# sourceMappingURL=boundedArray.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedArray.js","sourceRoot":"","sources":["../../src/validations/boundedArray.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAA6B,EAC7B,MAA+C,EAAE,EACvB,EAAE,CAC5B,CAAC,CAAC,OAAO,CACP,OAAO,GAAG,KAAK,QAAQ;IACrB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC,CAAC,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,CAAC,IAAI,CACJ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EACd,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,EACzB,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CACrB;QACH,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EACvD,CAAC,KAAK,EAAE,EAAE,CACR,mCAAmC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,0BAA0B,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAC/K,CAAC"}
@@ -0,0 +1,6 @@
1
+ import * as v from "valibot";
2
+ /** An integer with a value within the given bounds */
3
+ export declare const boundedInteger: (req?: number | {
4
+ min?: number;
5
+ max?: number;
6
+ }) => v.GenericSchema<number>;
@@ -0,0 +1,8 @@
1
+ import * as v from "valibot";
2
+ /** An integer with a value within the given bounds */
3
+ export const boundedInteger = (req = {}) => v.message(typeof req === `number`
4
+ ? v.pipe(v.number(), v.integer(), v.value(req))
5
+ : typeof req.max === `number`
6
+ ? v.pipe(v.number(), v.integer(), v.minValue(req.min ?? 0), v.maxValue(req.max))
7
+ : 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
+ //# sourceMappingURL=boundedInteger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedInteger.js","sourceRoot":"","sources":["../../src/validations/boundedInteger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,sDAAsD;AACtD,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,MAA+C,EAAE,EACxB,EAAE,CAC3B,CAAC,CAAC,OAAO,CACP,OAAO,GAAG,KAAK,QAAQ;IACrB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC,CAAC,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,CAAC,IAAI,CACJ,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,OAAO,EAAE,EACX,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,EACxB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CACpB;QACH,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAC/D,CAAC,KAAK,EAAE,EAAE,CACR,oCAAoC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,yBAAyB,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CACvL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import * as v from "valibot";
2
+ /** A non-empty string with a length within the given bounds */
3
+ export declare const boundedString: (req?: number | {
4
+ min?: number;
5
+ max?: number;
6
+ }) => v.GenericSchema<string>;
@@ -0,0 +1,8 @@
1
+ import * as v from "valibot";
2
+ /** A non-empty string with a length within the given bounds */
3
+ export const boundedString = (req = {}) => v.message(typeof req === `number`
4
+ ? v.pipe(v.string(), v.length(req))
5
+ : typeof req.max === `number`
6
+ ? v.pipe(v.string(), v.minLength(req.min ?? 1), v.maxLength(req.max))
7
+ : 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}`);
8
+ //# sourceMappingURL=boundedString.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundedString.js","sourceRoot":"","sources":["../../src/validations/boundedString.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,+DAA+D;AAC/D,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAA+C,EAAE,EACxB,EAAE,CAC3B,CAAC,CAAC,OAAO,CACP,OAAO,GAAG,KAAK,QAAQ;IACrB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EACnD,CAAC,KAAK,EAAE,EAAE,CACR,mCAAmC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,0BAA0B,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAC/K,CAAC"}
@@ -1,3 +1,4 @@
1
+ import * as v from "valibot";
1
2
  export declare const datauriRegex: RegExp;
2
3
  /**
3
4
  * Extracts metadata from a given Data URI such as it's
@@ -16,4 +17,4 @@ export declare const toBase64: (data: string) => string;
16
17
  /**
17
18
  * Validates that a string is a [data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme)
18
19
  */
19
- export declare const datauri: import("valibot").SchemaWithPipe<readonly [import("valibot").CustomSchema<string, import("valibot").ErrorMessage<import("valibot").CustomIssue> | undefined>, import("valibot").TitleAction<string, "datauri">]>;
20
+ export declare const datauri: v.GenericSchema<string>;
@@ -1,4 +1,4 @@
1
- import { custom, is, nonEmpty, pipe, regex, string, title } from "valibot";
1
+ import * as v from "valibot";
2
2
  export 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;
3
3
  /**
4
4
  * Extracts metadata from a given Data URI such as it's
@@ -16,5 +16,5 @@ export const toBase64 = (data) => typeof Buffer !== `undefined`
16
16
  /**
17
17
  * Validates that a string is a [data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme)
18
18
  */
19
- export const datauri = pipe(custom((val) => is(pipe(string(), nonEmpty(), regex(datauriRegex)), val), `Invalid Data URI`), title(`datauri`));
19
+ export const datauri = v.pipe(v.custom((val) => typeof val === `string` && val.length > 0 && datauriRegex.test(val), `Invalid Data URI`), v.title(`datauri`));
20
20
  //# sourceMappingURL=datauri.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"datauri.js","sourceRoot":"","sources":["../../src/validations/datauri.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE3E,MAAM,CAAC,MAAM,YAAY,GACvB,8LAA8L,CAAC;AAEjM;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,GAAW,EAOV,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE,CAC/C,OAAO,MAAM,KAAK,WAAW;IAC3B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE;IACxC,CAAC,CAAC,IAAI,CACF,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;SACzD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CACrB,CAAC;AAER;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CACzB,MAAM,CACJ,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,EACjE,kBAAkB,CACnB,EACD,KAAK,CAAC,SAAS,CAAC,CACjB,CAAC"}
1
+ {"version":3,"file":"datauri.js","sourceRoot":"","sources":["../../src/validations/datauri.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,MAAM,CAAC,MAAM,YAAY,GACvB,8LAA8L,CAAC;AAEjM;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,GAAW,EAOV,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE,CAC/C,OAAO,MAAM,KAAK,WAAW;IAC3B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE;IACxC,CAAC,CAAC,IAAI,CACF,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;SACzD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CACrB,CAAC;AAER;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAA4B,CAAC,CAAC,IAAI,CACpD,CAAC,CAAC,MAAM,CACN,CAAC,GAAG,EAAE,EAAE,CACN,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EACrE,kBAAkB,CACnB,EACD,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CACnB,CAAC"}
@@ -1,7 +1,12 @@
1
1
  export * from "./asDigits.js";
2
2
  export * from "./asInteger.js";
3
3
  export * from "./bitfield.js";
4
+ export * from "./boundedArray.js";
5
+ export * from "./boundedInteger.js";
6
+ export * from "./boundedString.js";
4
7
  export * from "./datauri.js";
5
8
  export * from "./hasMimeType.js";
6
9
  export * from "./toBlob.js";
7
10
  export * from "./snowflake.js";
11
+ export * from "./timestamp.js";
12
+ export * from "./url.js";
@@ -1,8 +1,13 @@
1
1
  export * from "./asDigits.js";
2
2
  export * from "./asInteger.js";
3
3
  export * from "./bitfield.js";
4
+ export * from "./boundedArray.js";
5
+ export * from "./boundedInteger.js";
6
+ export * from "./boundedString.js";
4
7
  export * from "./datauri.js";
5
8
  export * from "./hasMimeType.js";
6
9
  export * from "./toBlob.js";
7
10
  export * from "./snowflake.js";
11
+ export * from "./timestamp.js";
12
+ export * from "./url.js";
8
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validations/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validations/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
@@ -1,5 +1,6 @@
1
+ import * as v from "valibot";
2
+ /** UNIX timestamp representing the first second of 2015 */
1
3
  export declare const DISCORD_EPOCH = 1420070400000n;
2
- export declare const snowflake: import("valibot").SchemaWithPipe<readonly [import("valibot").CustomSchema<string, import("valibot").ErrorMessage<import("valibot").CustomIssue> | undefined>, import("valibot").TitleAction<string, "snowflake">]>;
3
4
  /**
4
5
  * Converts a `snowflake` string to a Date relative to the given epoch
5
6
  *
@@ -9,18 +10,16 @@ export declare const snowflake: import("valibot").SchemaWithPipe<readonly [impor
9
10
  */
10
11
  export declare const snowflakeToDate: (
11
12
  /** A snowflake string to convert */
12
- val: string,
13
+ val: string | number | bigint,
13
14
  /** time in milliseconds to use as the epoch to derive a Date from */
14
15
  epoch?: bigint) => Date;
15
16
  /**
16
- * Converts a Date to a `snowflake` string relative to the given epoch
17
+ * An up to 64-bit unsigned numeric value derived from a timestamp which
18
+ * serves as a unique identifier within Discord.
17
19
  *
18
- * Uses Discord's epoch by default
19
- *
20
- * https://discord.com/developers/docs/reference#snowflakes
20
+ * Validates whether a given `number`, `bigint`, or numeric `string` is
21
+ * a valid [Snowflake](https://discord.com/developers/docs/reference#snowflakes)
22
+ * by checking if it's derived timestamp is a valid time at or after
23
+ * the Discord epoch (the first second of 2015, ie: `1420070400000`).
21
24
  */
22
- export declare const dateToSnowflake: (
23
- /** A Date to convert to a `snowflake` */
24
- val: Date,
25
- /** time in milliseconds to use as the epoch to derive a `snowflake` from */
26
- epoch?: bigint) => string;
25
+ export declare const snowflake: v.GenericSchema<string>;
@@ -1,12 +1,8 @@
1
- import { custom, pipe, transform, union, string, number, is, title } from "valibot";
1
+ import * as v from "valibot";
2
2
  import { isNonNullable } from "../utils/isNonNullable.js";
3
+ import { isNumericString } from "../utils/isNumericString.js";
4
+ /** UNIX timestamp representing the first second of 2015 */
3
5
  export const DISCORD_EPOCH = 1420070400000n;
4
- export const snowflake = pipe(custom((val) => isNonNullable(val) &&
5
- (typeof val === `bigint` ||
6
- typeof val === `number` ||
7
- typeof val === `string`)
8
- ? is(pipe(union([string(), number()]), transform((input) => new Date(input))), Number((BigInt(val) >> 22n) + DISCORD_EPOCH))
9
- : false, `Invalid Snowflake ID`), title(`snowflake`));
10
6
  /**
11
7
  * Converts a `snowflake` string to a Date relative to the given epoch
12
8
  *
@@ -20,15 +16,24 @@ val,
20
16
  /** time in milliseconds to use as the epoch to derive a Date from */
21
17
  epoch = DISCORD_EPOCH) => new Date(Number((BigInt(val) >> 22n) + epoch));
22
18
  /**
23
- * Converts a Date to a `snowflake` string relative to the given epoch
24
- *
25
- * Uses Discord's epoch by default
19
+ * An up to 64-bit unsigned numeric value derived from a timestamp which
20
+ * serves as a unique identifier within Discord.
26
21
  *
27
- * https://discord.com/developers/docs/reference#snowflakes
22
+ * Validates whether a given `number`, `bigint`, or numeric `string` is
23
+ * a valid [Snowflake](https://discord.com/developers/docs/reference#snowflakes)
24
+ * by checking if it's derived timestamp is a valid time at or after
25
+ * the Discord epoch (the first second of 2015, ie: `1420070400000`).
28
26
  */
29
- export const dateToSnowflake = (
30
- /** A Date to convert to a `snowflake` */
31
- val,
32
- /** time in milliseconds to use as the epoch to derive a `snowflake` from */
33
- epoch = DISCORD_EPOCH) => String((BigInt(val.getMilliseconds()) - epoch) << 22n);
27
+ export const snowflake = v.pipe(v.custom((val) =>
28
+ // at runtime this could be any value, so filter out
29
+ // obviously invalid input first
30
+ isNonNullable(val) &&
31
+ // then verify we have a numeric value
32
+ (typeof val === `bigint` ||
33
+ typeof val === `number` ||
34
+ isNumericString(val)) &&
35
+ // finally, verify that it accurately represents ms
36
+ // at or after the Discord epoch (timestamps before
37
+ // that cannot possibly be a valid Discord snowflake)
38
+ snowflakeToDate(val).getTime() >= DISCORD_EPOCH, `Invalid Snowflake`), v.title(`snowflake`));
34
39
  //# sourceMappingURL=snowflake.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snowflake.js","sourceRoot":"","sources":["../../src/validations/snowflake.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,IAAI,EACJ,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,EACN,EAAE,EACF,KAAK,EACN,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAC3B,MAAM,CACJ,CAAC,GAAG,EAAE,EAAE,CACN,aAAa,CAAC,GAAG,CAAC;IAClB,CAAC,OAAO,GAAG,KAAK,QAAQ;QACtB,OAAO,GAAG,KAAK,QAAQ;QACvB,OAAO,GAAG,KAAK,QAAQ,CAAC;IACxB,CAAC,CAAC,EAAE,CACA,IAAI,CACF,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,EAC3B,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CACtC,EACD,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,aAAa,CAAC,CAC7C;IACH,CAAC,CAAC,KAAK,EACX,sBAAsB,CACvB,EACD,KAAK,CAAC,WAAW,CAAC,CACnB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;AAC7B,oCAAoC;AACpC,GAAW;AACX,qEAAqE;AACrE,KAAK,GAAG,aAAa,EACf,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;AAC7B,yCAAyC;AACzC,GAAS;AACT,4EAA4E;AAC5E,KAAK,GAAG,aAAa,EACb,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"snowflake.js","sourceRoot":"","sources":["../../src/validations/snowflake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;AAC7B,oCAAoC;AACpC,GAA6B;AAC7B,qEAAqE;AACrE,KAAK,GAAG,aAAa,EACf,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAA4B,CAAC,CAAC,IAAI,CACtD,CAAC,CAAC,MAAM,CACN,CAAC,GAAG,EAAE,EAAE;AACN,oDAAoD;AACpD,gCAAgC;AAChC,aAAa,CAAC,GAAG,CAAC;IAClB,sCAAsC;IACtC,CAAC,OAAO,GAAG,KAAK,QAAQ;QACtB,OAAO,GAAG,KAAK,QAAQ;QACvB,eAAe,CAAC,GAAG,CAAC,CAAC;IACvB,mDAAmD;IACnD,mDAAmD;IACnD,qDAAqD;IACrD,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,IAAI,aAAa,EACjD,mBAAmB,CACpB,EACD,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import * as v from "valibot";
2
+ /** An [ISO8601](https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf) timestamp */
3
+ export declare const timestamp: v.GenericSchema<string>;
@@ -0,0 +1,4 @@
1
+ import * as v from "valibot";
2
+ /** An [ISO8601](https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf) timestamp */
3
+ export const timestamp = v.message(v.pipe(v.string(), v.isoTimestamp()), (issue) => `Expected a valid timestamp, received: ${issue.received}`);
4
+ //# sourceMappingURL=timestamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp.js","sourceRoot":"","sources":["../../src/validations/timestamp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,sHAAsH;AACtH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAChC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,EACpC,CAAC,KAAK,EAAE,EAAE,CAAC,yCAAyC,KAAK,CAAC,QAAQ,EAAE,CAC1C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import * as v from "valibot";
2
+ export declare const url: v.GenericSchema<string>;
@@ -0,0 +1,3 @@
1
+ import * as v from "valibot";
2
+ export const url = v.message(v.pipe(v.string(), v.url()), (issue) => `Expected a valid URL, received: ${issue.received}`);
3
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/validations/url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,MAAM,CAAC,MAAM,GAAG,GAA4B,CAAC,CAAC,OAAO,CACnD,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAC3B,CAAC,KAAK,EAAE,EAAE,CAAC,mCAAmC,KAAK,CAAC,QAAQ,EAAE,CAC/D,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@discordkit/core",
3
3
  "description": "Core utility functions for Discordkit",
4
- "version": "3.0.2",
4
+ "version": "3.2.0",
5
5
  "license": "MIT",
6
6
  "author": "Drake Costa <drake@saeris.gg> (https://saeris.gg)",
7
7
  "keywords": [