@md-oss/common 0.1.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 (161) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +335 -0
  3. package/dist/api/errors.cjs +2 -0
  4. package/dist/api/errors.cjs.map +1 -0
  5. package/dist/api/errors.d.cts +53 -0
  6. package/dist/api/errors.d.mts +53 -0
  7. package/dist/api/errors.mjs +2 -0
  8. package/dist/api/errors.mjs.map +1 -0
  9. package/dist/api/index.cjs +2 -0
  10. package/dist/api/index.cjs.map +1 -0
  11. package/dist/api/index.d.cts +4 -0
  12. package/dist/api/index.d.mts +4 -0
  13. package/dist/api/index.mjs +2 -0
  14. package/dist/api/index.mjs.map +1 -0
  15. package/dist/api/requests.d.cts +36 -0
  16. package/dist/api/requests.d.mts +36 -0
  17. package/dist/api/status-codes.cjs +2 -0
  18. package/dist/api/status-codes.cjs.map +1 -0
  19. package/dist/api/status-codes.d.cts +72 -0
  20. package/dist/api/status-codes.d.mts +72 -0
  21. package/dist/api/status-codes.mjs +2 -0
  22. package/dist/api/status-codes.mjs.map +1 -0
  23. package/dist/arrays-BkHBzTDO.mjs +2 -0
  24. package/dist/arrays-BkHBzTDO.mjs.map +1 -0
  25. package/dist/arrays-CElcW69H.d.cts +43 -0
  26. package/dist/arrays-CElcW69H.d.mts +43 -0
  27. package/dist/arrays-DaB1Xn47.cjs +2 -0
  28. package/dist/arrays-DaB1Xn47.cjs.map +1 -0
  29. package/dist/constants/bytes.cjs +2 -0
  30. package/dist/constants/bytes.cjs.map +1 -0
  31. package/dist/constants/bytes.d.cts +19 -0
  32. package/dist/constants/bytes.d.mts +19 -0
  33. package/dist/constants/bytes.mjs +2 -0
  34. package/dist/constants/bytes.mjs.map +1 -0
  35. package/dist/constants/discord.cjs +2 -0
  36. package/dist/constants/discord.cjs.map +1 -0
  37. package/dist/constants/discord.d.cts +25 -0
  38. package/dist/constants/discord.d.mts +25 -0
  39. package/dist/constants/discord.mjs +2 -0
  40. package/dist/constants/discord.mjs.map +1 -0
  41. package/dist/constants/index.cjs +2 -0
  42. package/dist/constants/index.cjs.map +1 -0
  43. package/dist/constants/index.d.cts +3 -0
  44. package/dist/constants/index.d.mts +3 -0
  45. package/dist/constants/index.mjs +2 -0
  46. package/dist/constants/index.mjs.map +1 -0
  47. package/dist/constants/time.cjs +2 -0
  48. package/dist/constants/time.cjs.map +1 -0
  49. package/dist/constants/time.d.cts +65 -0
  50. package/dist/constants/time.d.mts +65 -0
  51. package/dist/constants/time.mjs +2 -0
  52. package/dist/constants/time.mjs.map +1 -0
  53. package/dist/index.cjs +2 -0
  54. package/dist/index.cjs.map +1 -0
  55. package/dist/index.d.cts +17 -0
  56. package/dist/index.d.mts +17 -0
  57. package/dist/index.mjs +2 -0
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/mime-types-Bjt4NvnE.d.cts +41 -0
  60. package/dist/mime-types-Bjt4NvnE.d.mts +41 -0
  61. package/dist/mime-types-BmvBrrZ7.cjs +2 -0
  62. package/dist/mime-types-BmvBrrZ7.cjs.map +1 -0
  63. package/dist/mime-types-D_K53zgk.mjs +2 -0
  64. package/dist/mime-types-D_K53zgk.mjs.map +1 -0
  65. package/dist/numbers-BmUSgeah.d.cts +46 -0
  66. package/dist/numbers-BmUSgeah.d.mts +46 -0
  67. package/dist/numbers-Bx9JTSQe.mjs +2 -0
  68. package/dist/numbers-Bx9JTSQe.mjs.map +1 -0
  69. package/dist/numbers-DuVx9Qiu.cjs +2 -0
  70. package/dist/numbers-DuVx9Qiu.cjs.map +1 -0
  71. package/dist/objects--cO_X3EV.mjs +2 -0
  72. package/dist/objects--cO_X3EV.mjs.map +1 -0
  73. package/dist/objects-CnGoVkh6.cjs +2 -0
  74. package/dist/objects-CnGoVkh6.cjs.map +1 -0
  75. package/dist/objects-cf8j7rS8.d.cts +26 -0
  76. package/dist/objects-cf8j7rS8.d.mts +26 -0
  77. package/dist/random-D1e1NTOt.cjs +2 -0
  78. package/dist/random-D1e1NTOt.cjs.map +1 -0
  79. package/dist/random-DbidGSrQ.mjs +2 -0
  80. package/dist/random-DbidGSrQ.mjs.map +1 -0
  81. package/dist/random-DpNyGGAZ.d.cts +28 -0
  82. package/dist/random-DpNyGGAZ.d.mts +28 -0
  83. package/dist/runtime-B-jA8ZxR.cjs +2 -0
  84. package/dist/runtime-B-jA8ZxR.cjs.map +1 -0
  85. package/dist/runtime-CbfL6Fgj.mjs +2 -0
  86. package/dist/runtime-CbfL6Fgj.mjs.map +1 -0
  87. package/dist/runtime-T8Kcf7Af.d.cts +28 -0
  88. package/dist/runtime-T8Kcf7Af.d.mts +28 -0
  89. package/dist/schemas.cjs +2 -0
  90. package/dist/schemas.cjs.map +1 -0
  91. package/dist/schemas.d.cts +36 -0
  92. package/dist/schemas.d.mts +36 -0
  93. package/dist/schemas.mjs +2 -0
  94. package/dist/schemas.mjs.map +1 -0
  95. package/dist/strings-B0BRwNX9.mjs +3 -0
  96. package/dist/strings-B0BRwNX9.mjs.map +1 -0
  97. package/dist/strings-DV446vv-.cjs +3 -0
  98. package/dist/strings-DV446vv-.cjs.map +1 -0
  99. package/dist/strings-DhPbrpq7.d.cts +47 -0
  100. package/dist/strings-DhPbrpq7.d.mts +47 -0
  101. package/dist/time-8KLG8kBO.d.cts +29 -0
  102. package/dist/time-D8Wfqzu6.d.mts +29 -0
  103. package/dist/time-DmJNWZeL.mjs +2 -0
  104. package/dist/time-DmJNWZeL.mjs.map +1 -0
  105. package/dist/time-yNkQSJnQ.cjs +2 -0
  106. package/dist/time-yNkQSJnQ.cjs.map +1 -0
  107. package/dist/utils/arrays.cjs +2 -0
  108. package/dist/utils/arrays.cjs.map +1 -0
  109. package/dist/utils/arrays.d.cts +1 -0
  110. package/dist/utils/arrays.d.mts +1 -0
  111. package/dist/utils/arrays.mjs +2 -0
  112. package/dist/utils/arrays.mjs.map +1 -0
  113. package/dist/utils/index.cjs +2 -0
  114. package/dist/utils/index.cjs.map +1 -0
  115. package/dist/utils/index.d.cts +9 -0
  116. package/dist/utils/index.d.mts +9 -0
  117. package/dist/utils/index.mjs +2 -0
  118. package/dist/utils/index.mjs.map +1 -0
  119. package/dist/utils/mime-types.cjs +2 -0
  120. package/dist/utils/mime-types.cjs.map +1 -0
  121. package/dist/utils/mime-types.d.cts +1 -0
  122. package/dist/utils/mime-types.d.mts +1 -0
  123. package/dist/utils/mime-types.mjs +2 -0
  124. package/dist/utils/mime-types.mjs.map +1 -0
  125. package/dist/utils/numbers.cjs +2 -0
  126. package/dist/utils/numbers.cjs.map +1 -0
  127. package/dist/utils/numbers.d.cts +1 -0
  128. package/dist/utils/numbers.d.mts +1 -0
  129. package/dist/utils/numbers.mjs +2 -0
  130. package/dist/utils/numbers.mjs.map +1 -0
  131. package/dist/utils/objects.cjs +2 -0
  132. package/dist/utils/objects.cjs.map +1 -0
  133. package/dist/utils/objects.d.cts +1 -0
  134. package/dist/utils/objects.d.mts +1 -0
  135. package/dist/utils/objects.mjs +2 -0
  136. package/dist/utils/objects.mjs.map +1 -0
  137. package/dist/utils/random.cjs +2 -0
  138. package/dist/utils/random.cjs.map +1 -0
  139. package/dist/utils/random.d.cts +1 -0
  140. package/dist/utils/random.d.mts +1 -0
  141. package/dist/utils/random.mjs +2 -0
  142. package/dist/utils/random.mjs.map +1 -0
  143. package/dist/utils/runtime.cjs +2 -0
  144. package/dist/utils/runtime.cjs.map +1 -0
  145. package/dist/utils/runtime.d.cts +1 -0
  146. package/dist/utils/runtime.d.mts +1 -0
  147. package/dist/utils/runtime.mjs +2 -0
  148. package/dist/utils/runtime.mjs.map +1 -0
  149. package/dist/utils/strings.cjs +2 -0
  150. package/dist/utils/strings.cjs.map +1 -0
  151. package/dist/utils/strings.d.cts +1 -0
  152. package/dist/utils/strings.d.mts +1 -0
  153. package/dist/utils/strings.mjs +2 -0
  154. package/dist/utils/strings.mjs.map +1 -0
  155. package/dist/utils/time.cjs +2 -0
  156. package/dist/utils/time.cjs.map +1 -0
  157. package/dist/utils/time.d.cts +2 -0
  158. package/dist/utils/time.d.mts +2 -0
  159. package/dist/utils/time.mjs +2 -0
  160. package/dist/utils/time.mjs.map +1 -0
  161. package/package.json +232 -0
package/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright 2026 Mirasaki Development
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # @md-oss/common
2
+
3
+ Constants, magic numbers, and utilities used commonly across projects.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Constants](#constants)
8
+ - [Utilities](#utilities)
9
+ - [API](#api)
10
+ - [Schemas](#schemas)
11
+
12
+ ## Constants
13
+
14
+ ### Byte Sizes
15
+ ```typescript
16
+ import { ByteMagic } from '@md-oss/common';
17
+
18
+ console.log(ByteMagic.MEGABYTE); // 1048576
19
+ console.log(ByteMagic.GIGABYTE); // 1073741824
20
+ ```
21
+
22
+ ### Discord Limits
23
+ ```typescript
24
+ import { DiscordMagic } from '@md-oss/common';
25
+
26
+ console.log(DiscordMagic.MESSAGE_CONTENT_MAX); // 2000
27
+ console.log(DiscordMagic.EMBED_DESCRIPTION_MAX); // 4096
28
+ console.log(DiscordMagic.FILE_SIZE_MAX); // 8388608 (8MB)
29
+ ```
30
+
31
+ ### Time Conversions
32
+ ```typescript
33
+ import { TimeMagic } from '@md-oss/common';
34
+
35
+ console.log(TimeMagic.SECOND); // 1000ms
36
+ console.log(TimeMagic.MINUTES_PER_HOUR); // 60
37
+ console.log(TimeMagic.MILLISECONDS_PER_DAY); // 86400000
38
+ ```
39
+
40
+ ## Utilities
41
+
42
+ ### Array Utilities
43
+ ```typescript
44
+ import { ArrayUtils } from '@md-oss/common';
45
+
46
+ // Chunk an array
47
+ ArrayUtils.chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
48
+
49
+ // Join with max items
50
+ ArrayUtils.join(['a', 'b', 'c', 'd'], { maxItems: 2 });
51
+ // "a, b, and 2 more..."
52
+
53
+ // Type guards
54
+ ArrayUtils.isStringArray(['a', 'b']); // true
55
+ ArrayUtils.isNumberArray([1, 2, 3]); // true
56
+ ```
57
+
58
+ ### String Utilities
59
+ ```typescript
60
+ import { StringUtils } from '@md-oss/common';
61
+
62
+ // Case conversions
63
+ StringUtils.camelCase('hello world'); // 'helloWorld'
64
+ StringUtils.kebabCase('HelloWorld'); // 'hello-world'
65
+ StringUtils.snakeCase('HelloWorld'); // 'hello_world'
66
+ StringUtils.titleCase('hello world'); // 'Hello World'
67
+ StringUtils.pascalCase('hello world'); // 'HelloWorld'
68
+
69
+ // String manipulation
70
+ StringUtils.truncate('hello world', 8); // 'hello...'
71
+ StringUtils.pluralize('item', 2); // 'items'
72
+ StringUtils.replaceTags('Hello {name}', { name: 'John' }); // 'Hello John'
73
+ StringUtils.isUrl('https://example.com'); // true
74
+ ```
75
+
76
+ ### Number Utilities
77
+ ```typescript
78
+ import { NumberUtils } from '@md-oss/common';
79
+
80
+ // Type checks
81
+ NumberUtils.isInt(42); // true
82
+ NumberUtils.isFloat(42.5); // true
83
+
84
+ // Statistics
85
+ NumberUtils.calculateMean([1, 2, 3, 4]); // 2.5
86
+ NumberUtils.calculateMedian([1, 2, 3, 4, 5]); // 3
87
+ NumberUtils.calculateVariance([1, 2, 3, 4]); // 1.25
88
+ NumberUtils.calculateStandardDeviation([1, 2, 3, 4]); // ~1.118
89
+
90
+ // Constants
91
+ NumberUtils.INT32_MAX; // 2147483647
92
+ NumberUtils.INT64_MAX; // 9223372036854775807n
93
+ ```
94
+
95
+ ### Object Utilities
96
+ ```typescript
97
+ import { ObjectUtils } from '@md-oss/common';
98
+
99
+ // Type guards
100
+ ObjectUtils.isObject({ a: 1 }); // true
101
+ ObjectUtils.isEmptyObject({}); // true
102
+
103
+ // Deep operations
104
+ const cloned = ObjectUtils.deepClone({ a: { b: 1 } });
105
+ const merged = ObjectUtils.deepMerge({ a: 1 }, { b: 2 }); // { a: 1, b: 2 }
106
+
107
+ // Nested value access
108
+ ObjectUtils.getNestedValue({ a: { b: { c: 1 } } }, 'a.b.c'); // 1
109
+ ObjectUtils.getNestedValue({ user: { name: 'John' } }, 'user.name'); // 'John'
110
+ ```
111
+
112
+ ### Random Utilities
113
+ ```typescript
114
+ import { RandomUtils } from '@md-oss/common';
115
+
116
+ // Random numbers
117
+ RandomUtils.randomInt(1, 10); // random int between 1-10
118
+ RandomUtils.randomFloat(0, 1); // random float between 0-1
119
+ RandomUtils.randomBoolean(); // true or false
120
+
121
+ // Random selections
122
+ RandomUtils.randomItem([1, 2, 3, 4, 5]); // random item
123
+ RandomUtils.randomKey({ a: 1, b: 2 }); // 'a' or 'b'
124
+ RandomUtils.randomValue({ a: 1, b: 2 }); // 1 or 2
125
+
126
+ // Random strings
127
+ RandomUtils.randomString(8, { useUppercase: true, useNumeric: true });
128
+ // e.g., 'A3bF9xK1'
129
+ ```
130
+
131
+ ### Time Utilities
132
+ ```typescript
133
+ import { TimeUtils } from '@md-oss/common';
134
+
135
+ // Unix timestamps
136
+ TimeUtils.unix(Date.now()); // current unix timestamp
137
+ TimeUtils.unixNow(); // shorthand for unix(Date.now())
138
+
139
+ // Human-readable durations
140
+ TimeUtils.humanReadableMs(5000); // '5 seconds'
141
+ TimeUtils.humanReadableMs(125000, 3); // '2 minutes and 5 seconds'
142
+
143
+ // Async utilities
144
+ await TimeUtils.sleep(1000); // sleep for 1 second
145
+
146
+ // Performance tracking
147
+ TimeUtils.hrTimeToMs([0, 123456789]); // convert hrtime to milliseconds
148
+ TimeUtils.bigIntDurationToHumanReadable(startTime); // format duration
149
+ ```
150
+
151
+ ### Runtime Utilities
152
+ ```typescript
153
+ import { RuntimeUtils } from '@md-oss/common';
154
+
155
+ // Sleep utilities
156
+ await RuntimeUtils.sleep(1000); // sleep for 1 second
157
+ await RuntimeUtils.sleepUntil(() => someCondition);
158
+ await RuntimeUtils.sleepUntilOrTimeout(() => someCondition, 5000);
159
+
160
+ // Await with timeout
161
+ const result = await RuntimeUtils.awaitOrTimeout(promise, 5000);
162
+
163
+ // Safe timeout/interval (handles values > INT32_MAX)
164
+ RuntimeUtils.safeSetTimeout(86400000, false, () => {
165
+ console.log('runs after 24 hours');
166
+ });
167
+
168
+ RuntimeUtils.safeSetInterval(1000, () => {
169
+ console.log('runs every second');
170
+ });
171
+
172
+ RuntimeUtils.safeSetAsyncInterval(1000, async () => {
173
+ await doAsyncWork();
174
+ });
175
+ ```
176
+
177
+ ### MIME Type Utilities
178
+ ```typescript
179
+ import { MimeTypeUtils } from '@md-oss/common';
180
+
181
+ // Validation
182
+ MimeTypeUtils.isAllowedMimeType('image/png', 'IMAGE'); // true
183
+ MimeTypeUtils.isAllowedMimeType('application/pdf', 'SAFE'); // true
184
+
185
+ // HTML input accept strings
186
+ MimeTypeUtils.getInputAccept('IMAGE');
187
+ // 'image/png,image/jpeg,image/webp,...'
188
+
189
+ // Type resolution
190
+ MimeTypeUtils.mimeTypeResolver('video/mp4'); // 'VIDEO'
191
+ MimeTypeUtils.mimeTypeResolver('application/pdf'); // 'DOCUMENT'
192
+
193
+ // Content disposition
194
+ MimeTypeUtils.isInlineContentDisposition('image/png'); // true
195
+ MimeTypeUtils.isInlineContentDisposition('application/zip'); // false
196
+ ```
197
+
198
+ ## API
199
+
200
+ ### Status Codes
201
+ ```typescript
202
+ import { statusCodes, type StatusCode } from '@md-oss/common';
203
+
204
+ // Use named status codes
205
+ statusCodes.OK; // 200
206
+ statusCodes.CREATED; // 201
207
+ statusCodes.BAD_REQUEST; // 400
208
+ statusCodes.UNAUTHORIZED; // 401
209
+ statusCodes.NOT_FOUND; // 404
210
+ statusCodes.INTERNAL_SERVER_ERROR; // 500
211
+ ```
212
+
213
+ ### API Errors
214
+ ```typescript
215
+ import { APIError, isAPIError, parseError } from '@md-oss/common';
216
+
217
+ // Create API errors
218
+ const error = new APIError(404, {
219
+ code: 'NOT_FOUND',
220
+ message: 'Resource not found',
221
+ details: { id: '123' }
222
+ });
223
+
224
+ // Alternative constructor syntax
225
+ const error2 = new APIError({
226
+ status: 400,
227
+ code: 'VALIDATION_ERROR',
228
+ message: 'Invalid input',
229
+ headers: { 'X-Custom': 'value' }
230
+ });
231
+
232
+ // Type guards
233
+ if (isAPIError(error)) {
234
+ console.log(error.statusCode, error.body.code);
235
+ }
236
+
237
+ // Parse unknown errors into APIError
238
+ try {
239
+ await someOperation();
240
+ } catch (err) {
241
+ const apiError = parseError(err, 'OPERATION_FAILED', 'Operation failed');
242
+ throw apiError;
243
+ }
244
+
245
+ // Serialize to JSON
246
+ const json = error.toJSON();
247
+ ```
248
+
249
+ ### Request/Response Types
250
+ ```typescript
251
+ import type {
252
+ MinimalRequest,
253
+ MinimalResponse,
254
+ MinimalNextFunction,
255
+ MinimalRequestHandler
256
+ } from '@md-oss/common';
257
+
258
+ // Framework-agnostic request handler types
259
+ const handler: MinimalRequestHandler = async (req, res, next) => {
260
+ const userIp = req.ip;
261
+ const params = req.params;
262
+ const query = req.query;
263
+
264
+ res.status(200).json({ success: true });
265
+ };
266
+ ```
267
+
268
+ ## Schemas
269
+
270
+ ### Zod Utilities
271
+ ```typescript
272
+ import {
273
+ isFieldRequired,
274
+ requiredKeys,
275
+ zodEnumFromObjectKeys,
276
+ paginationQuerySchema
277
+ } from '@md-oss/common';
278
+ import { z } from 'zod';
279
+
280
+ // Check if a field is required
281
+ const schema = z.object({
282
+ name: z.string(),
283
+ age: z.number().optional(),
284
+ });
285
+ isFieldRequired(schema, 'name'); // true
286
+ isFieldRequired(schema, 'age'); // false
287
+
288
+ // Get all required keys
289
+ const required = requiredKeys(schema);
290
+ // ['name']
291
+
292
+ // Create enum from object keys
293
+ const roles = { ADMIN: 1, USER: 2, GUEST: 3 };
294
+ const roleEnum = zodEnumFromObjectKeys(roles);
295
+ // z.enum(['ADMIN', 'USER', 'GUEST'])
296
+
297
+ // Pagination schema
298
+ const paginationSchema = paginationQuerySchema({
299
+ min: 1,
300
+ max: 100,
301
+ defaultLimit: 25
302
+ });
303
+
304
+ // Parse pagination query
305
+ const { limit, offset } = paginationSchema.parse({
306
+ limit: '50',
307
+ offset: '0'
308
+ });
309
+ ```
310
+
311
+ ### Signed URL Schema
312
+ ```typescript
313
+ import { signedUrlSchema, type SignedUrlSchema } from '@md-oss/common';
314
+
315
+ // Validate signed URL parameters
316
+ const params = signedUrlSchema.parse({
317
+ expires: 1640995200,
318
+ sig: 'abc123',
319
+ ref: 'user-123'
320
+ });
321
+ ```
322
+
323
+ ### Pagination Type
324
+ ```typescript
325
+ import type { Pagination } from '@md-oss/common';
326
+
327
+ const pagination: Pagination = {
328
+ totalItems: 100,
329
+ currentPage: 1,
330
+ itemsPerPage: 25,
331
+ totalPages: 4,
332
+ limit: 25,
333
+ offset: 0
334
+ };
335
+ ```
@@ -0,0 +1,2 @@
1
+ "use strict";var u=Object.defineProperty;var o=(s,e)=>u(s,"name",{value:e,configurable:!0});const{NODE_ENV:d}=process.env;class t extends Error{static{o(this,"APIError")}ok=!1;statusCode;headers;body;constructor(e,i,b){super(),typeof e=="object"?(this.statusCode=e.status,this.headers=e.headers??{},this.body={code:e.code,message:e.message,details:e.details}):(this.statusCode=e,this.headers=b??{},this.body=i||{code:"INTERNAL_SERVER_ERROR",message:"An error occurred, but no additional information is available."}),this.message=`[${this.body.code}]: ${this.body.message}`}toJSON(){return{ok:this.ok,statusCode:this.statusCode,body:this.body,headers:this.headers}}}const n=o(s=>s instanceof t?!0:a(s)?(s=new t(s.statusCode,{code:s.body.code,message:s.body.message,details:s.body.details}),!0):!1,"isAPIError"),a=o(s=>typeof s=="object"&&s!==null&&"ok"in s&&s.ok===!1&&"statusCode"in s&&typeof s.statusCode=="number"&&"body"in s&&typeof s.body=="object"&&s.body!==null&&"code"in s.body&&typeof s.body.code=="string"&&"message"in s.body&&typeof s.body.message=="string","isAPIErrorResponse"),c=o((s,e,i)=>n(s)?new t(s.statusCode,{code:e,message:s.body.message,details:s.body.details}):a(s)?new t(s.statusCode,{code:e,message:s.body.message,details:s.body.details}):s instanceof Error?new t(500,{code:e,message:i,details:d==="production"?void 0:{message:s.message,stack:s.stack}}):new t(500,{code:e,message:i,details:d==="production"?void 0:JSON.stringify(s,null,2)}),"parseError");exports.APIError=t,exports.isAPIError=n,exports.isAPIErrorResponse=a,exports.parseError=c;
2
+ //# sourceMappingURL=errors.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.cjs","sources":["../../src/api/errors.ts"],"sourcesContent":["import type { StatusCode } from './status-codes';\n\nconst { NODE_ENV } = process.env;\n\ntype APIErrorResponse = {\n\tok: false;\n\tstatusCode: StatusCode;\n\tbody: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t};\n\theaders?: HeadersInit;\n};\n\ntype HeadersInit = Record<string, string> | Array<[string, string]> | Headers;\n\nclass APIError extends Error {\n\treadonly ok = false;\n\treadonly statusCode: StatusCode;\n\treadonly headers: HeadersInit;\n\treadonly body: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t};\n\n\tconstructor(body: {\n\t\tstatus: StatusCode;\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t\theaders?: HeadersInit;\n\t});\n\tconstructor(\n\t\tstatusCode: StatusCode,\n\t\tbody: {\n\t\t\tcode: string;\n\t\t\tmessage: string;\n\t\t\tdetails?: string | Record<string, unknown>;\n\t\t},\n\t\theaders?: HeadersInit\n\t);\n\tconstructor(\n\t\tstatusCodeOrBody:\n\t\t\t| StatusCode\n\t\t\t| {\n\t\t\t\t\tstatus: StatusCode;\n\t\t\t\t\tcode: string;\n\t\t\t\t\tmessage: string;\n\t\t\t\t\tdetails?: string | Record<string, unknown>;\n\t\t\t\t\theaders?: HeadersInit;\n\t\t\t },\n\t\tbody?: {\n\t\t\tcode: string;\n\t\t\tmessage: string;\n\t\t\tdetails?: string | Record<string, unknown>;\n\t\t},\n\t\theaders?: HeadersInit\n\t) {\n\t\tsuper();\n\n\t\tif (typeof statusCodeOrBody === 'object') {\n\t\t\t// Single argument signature\n\t\t\tthis.statusCode = statusCodeOrBody.status;\n\t\t\tthis.headers = statusCodeOrBody.headers ?? {};\n\t\t\tthis.body = {\n\t\t\t\tcode: statusCodeOrBody.code,\n\t\t\t\tmessage: statusCodeOrBody.message,\n\t\t\t\tdetails: statusCodeOrBody.details,\n\t\t\t};\n\t\t} else {\n\t\t\t// Multi-argument signature\n\t\t\tthis.statusCode = statusCodeOrBody;\n\t\t\tthis.headers = headers ?? {};\n\t\t\tthis.body = body || {\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage:\n\t\t\t\t\t'An error occurred, but no additional information is available.',\n\t\t\t};\n\t\t}\n\n\t\tthis.message = `[${this.body.code}]: ${this.body.message}`;\n\t}\n\n\ttoJSON(): APIErrorResponse {\n\t\treturn {\n\t\t\tok: this.ok,\n\t\t\tstatusCode: this.statusCode,\n\t\t\tbody: this.body,\n\t\t\theaders: this.headers,\n\t\t} satisfies APIErrorResponse;\n\t}\n}\n\n//\n// Start Guards\n//\n\ninterface APISuccessResponse<T> {\n\tok: true;\n\tcode: number;\n\tmessage: string | null;\n\tdata: T;\n}\n\nconst isAPIError = (r: unknown): r is APIError => {\n\tif (r instanceof APIError) {\n\t\treturn true;\n\t}\n\n\tif (isAPIErrorResponse(r)) {\n\t\tr = new APIError(r.statusCode, {\n\t\t\tcode: r.body.code,\n\t\t\tmessage: r.body.message,\n\t\t\tdetails: r.body.details,\n\t\t});\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nconst isAPIErrorResponse = (r: unknown): r is APIErrorResponse => {\n\treturn (\n\t\ttypeof r === 'object' &&\n\t\tr !== null &&\n\t\t'ok' in r &&\n\t\tr.ok === false &&\n\t\t'statusCode' in r &&\n\t\ttypeof r.statusCode === 'number' &&\n\t\t'body' in r &&\n\t\ttypeof r.body === 'object' &&\n\t\tr.body !== null &&\n\t\t'code' in r.body &&\n\t\ttypeof r.body.code === 'string' &&\n\t\t'message' in r.body &&\n\t\ttypeof r.body.message === 'string'\n\t);\n};\n\n/**\n * Parses an unknown error into a standardized APIError. The provided code and message\n * will be used for the resulting APIError, while details from the original error\n * will be included when not in production mode.\n */\nconst parseError = (\n\terror: unknown,\n\tcode: string,\n\tmessage: string\n): APIError => {\n\tif (isAPIError(error)) {\n\t\treturn new APIError(error.statusCode, {\n\t\t\tcode,\n\t\t\tmessage: error.body.message,\n\t\t\tdetails: error.body.details,\n\t\t});\n\t}\n\n\tif (isAPIErrorResponse(error)) {\n\t\treturn new APIError(error.statusCode, {\n\t\t\tcode,\n\t\t\tmessage: error.body.message,\n\t\t\tdetails: error.body.details,\n\t\t});\n\t}\n\n\tif (error instanceof Error) {\n\t\treturn new APIError(500, {\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tdetails:\n\t\t\t\tNODE_ENV === 'production'\n\t\t\t\t\t? undefined\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\t\tstack: error.stack,\n\t\t\t\t\t\t},\n\t\t});\n\t}\n\n\treturn new APIError(500, {\n\t\tcode,\n\t\tmessage,\n\t\tdetails:\n\t\t\tNODE_ENV === 'production' ? undefined : JSON.stringify(error, null, 2),\n\t});\n};\n\nexport {\n\tAPIError,\n\ttype APIErrorResponse,\n\ttype APISuccessResponse,\n\tisAPIError,\n\tisAPIErrorResponse,\n\tparseError,\n};\n"],"names":["NODE_ENV","APIError","__name","statusCodeOrBody","body","headers","isAPIError","r","isAPIErrorResponse","parseError","error","code","message"],"mappings":"4FAEA,KAAM,CAAE,SAAAA,CAAA,EAAa,QAAQ,IAe7B,MAAMC,UAAiB,KAAM,OAAA,CAAAC,EAAA,iBACnB,GAAK,GACL,WACA,QACA,KAsBT,YACCC,EASAC,EAKAC,EACC,CACD,MAAA,EAEI,OAAOF,GAAqB,UAE/B,KAAK,WAAaA,EAAiB,OACnC,KAAK,QAAUA,EAAiB,SAAW,CAAA,EAC3C,KAAK,KAAO,CACX,KAAMA,EAAiB,KACvB,QAASA,EAAiB,QAC1B,QAASA,EAAiB,OAAA,IAI3B,KAAK,WAAaA,EAClB,KAAK,QAAUE,GAAW,CAAA,EAC1B,KAAK,KAAOD,GAAQ,CACnB,KAAM,wBACN,QACC,gEAAA,GAIH,KAAK,QAAU,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,EACzD,CAEA,QAA2B,CAC1B,MAAO,CACN,GAAI,KAAK,GACT,WAAY,KAAK,WACjB,KAAM,KAAK,KACX,QAAS,KAAK,OAAA,CAEhB,CACD,CAaA,MAAME,EAAaJ,EAACK,GACfA,aAAaN,EACT,GAGJO,EAAmBD,CAAC,GACvBA,EAAI,IAAIN,EAASM,EAAE,WAAY,CAC9B,KAAMA,EAAE,KAAK,KACb,QAASA,EAAE,KAAK,QAChB,QAASA,EAAE,KAAK,OAAA,CAChB,EACM,IAGD,GAdW,cAiBbC,EAAqBN,EAACK,GAE1B,OAAOA,GAAM,UACbA,IAAM,MACN,OAAQA,GACRA,EAAE,KAAO,IACT,eAAgBA,GAChB,OAAOA,EAAE,YAAe,UACxB,SAAUA,GACV,OAAOA,EAAE,MAAS,UAClBA,EAAE,OAAS,MACX,SAAUA,EAAE,MACZ,OAAOA,EAAE,KAAK,MAAS,UACvB,YAAaA,EAAE,MACf,OAAOA,EAAE,KAAK,SAAY,SAdD,sBAuBrBE,EAAaP,EAAA,CAClBQ,EACAC,EACAC,IAEIN,EAAWI,CAAK,EACZ,IAAIT,EAASS,EAAM,WAAY,CACrC,KAAAC,EACA,QAASD,EAAM,KAAK,QACpB,QAASA,EAAM,KAAK,OAAA,CACpB,EAGEF,EAAmBE,CAAK,EACpB,IAAIT,EAASS,EAAM,WAAY,CACrC,KAAAC,EACA,QAASD,EAAM,KAAK,QACpB,QAASA,EAAM,KAAK,OAAA,CACpB,EAGEA,aAAiB,MACb,IAAIT,EAAS,IAAK,CACxB,KAAAU,EACA,QAAAC,EACA,QACCZ,IAAa,aACV,OACA,CACA,QAASU,EAAM,QACf,MAAOA,EAAM,KAAA,CACd,CACH,EAGK,IAAIT,EAAS,IAAK,CACxB,KAAAU,EACA,QAAAC,EACA,QACCZ,IAAa,aAAe,OAAY,KAAK,UAAUU,EAAO,KAAM,CAAC,CAAA,CACtE,EAxCiB"}
@@ -0,0 +1,53 @@
1
+ import { StatusCode } from './status-codes.cjs';
2
+
3
+ type APIErrorResponse = {
4
+ ok: false;
5
+ statusCode: StatusCode;
6
+ body: {
7
+ code: string;
8
+ message: string;
9
+ details?: string | Record<string, unknown>;
10
+ };
11
+ headers?: HeadersInit;
12
+ };
13
+ type HeadersInit = Record<string, string> | Array<[string, string]> | Headers;
14
+ declare class APIError extends Error {
15
+ readonly ok = false;
16
+ readonly statusCode: StatusCode;
17
+ readonly headers: HeadersInit;
18
+ readonly body: {
19
+ code: string;
20
+ message: string;
21
+ details?: string | Record<string, unknown>;
22
+ };
23
+ constructor(body: {
24
+ status: StatusCode;
25
+ code: string;
26
+ message: string;
27
+ details?: string | Record<string, unknown>;
28
+ headers?: HeadersInit;
29
+ });
30
+ constructor(statusCode: StatusCode, body: {
31
+ code: string;
32
+ message: string;
33
+ details?: string | Record<string, unknown>;
34
+ }, headers?: HeadersInit);
35
+ toJSON(): APIErrorResponse;
36
+ }
37
+ interface APISuccessResponse<T> {
38
+ ok: true;
39
+ code: number;
40
+ message: string | null;
41
+ data: T;
42
+ }
43
+ declare const isAPIError: (r: unknown) => r is APIError;
44
+ declare const isAPIErrorResponse: (r: unknown) => r is APIErrorResponse;
45
+ /**
46
+ * Parses an unknown error into a standardized APIError. The provided code and message
47
+ * will be used for the resulting APIError, while details from the original error
48
+ * will be included when not in production mode.
49
+ */
50
+ declare const parseError: (error: unknown, code: string, message: string) => APIError;
51
+
52
+ export { APIError, isAPIError, isAPIErrorResponse, parseError };
53
+ export type { APIErrorResponse, APISuccessResponse };
@@ -0,0 +1,53 @@
1
+ import { StatusCode } from './status-codes.mjs';
2
+
3
+ type APIErrorResponse = {
4
+ ok: false;
5
+ statusCode: StatusCode;
6
+ body: {
7
+ code: string;
8
+ message: string;
9
+ details?: string | Record<string, unknown>;
10
+ };
11
+ headers?: HeadersInit;
12
+ };
13
+ type HeadersInit = Record<string, string> | Array<[string, string]> | Headers;
14
+ declare class APIError extends Error {
15
+ readonly ok = false;
16
+ readonly statusCode: StatusCode;
17
+ readonly headers: HeadersInit;
18
+ readonly body: {
19
+ code: string;
20
+ message: string;
21
+ details?: string | Record<string, unknown>;
22
+ };
23
+ constructor(body: {
24
+ status: StatusCode;
25
+ code: string;
26
+ message: string;
27
+ details?: string | Record<string, unknown>;
28
+ headers?: HeadersInit;
29
+ });
30
+ constructor(statusCode: StatusCode, body: {
31
+ code: string;
32
+ message: string;
33
+ details?: string | Record<string, unknown>;
34
+ }, headers?: HeadersInit);
35
+ toJSON(): APIErrorResponse;
36
+ }
37
+ interface APISuccessResponse<T> {
38
+ ok: true;
39
+ code: number;
40
+ message: string | null;
41
+ data: T;
42
+ }
43
+ declare const isAPIError: (r: unknown) => r is APIError;
44
+ declare const isAPIErrorResponse: (r: unknown) => r is APIErrorResponse;
45
+ /**
46
+ * Parses an unknown error into a standardized APIError. The provided code and message
47
+ * will be used for the resulting APIError, while details from the original error
48
+ * will be included when not in production mode.
49
+ */
50
+ declare const parseError: (error: unknown, code: string, message: string) => APIError;
51
+
52
+ export { APIError, isAPIError, isAPIErrorResponse, parseError };
53
+ export type { APIErrorResponse, APISuccessResponse };
@@ -0,0 +1,2 @@
1
+ var u=Object.defineProperty;var o=(s,e)=>u(s,"name",{value:e,configurable:!0});const{NODE_ENV:d}=process.env;class t extends Error{static{o(this,"APIError")}ok=!1;statusCode;headers;body;constructor(e,i,b){super(),typeof e=="object"?(this.statusCode=e.status,this.headers=e.headers??{},this.body={code:e.code,message:e.message,details:e.details}):(this.statusCode=e,this.headers=b??{},this.body=i||{code:"INTERNAL_SERVER_ERROR",message:"An error occurred, but no additional information is available."}),this.message=`[${this.body.code}]: ${this.body.message}`}toJSON(){return{ok:this.ok,statusCode:this.statusCode,body:this.body,headers:this.headers}}}const n=o(s=>s instanceof t?!0:a(s)?(s=new t(s.statusCode,{code:s.body.code,message:s.body.message,details:s.body.details}),!0):!1,"isAPIError"),a=o(s=>typeof s=="object"&&s!==null&&"ok"in s&&s.ok===!1&&"statusCode"in s&&typeof s.statusCode=="number"&&"body"in s&&typeof s.body=="object"&&s.body!==null&&"code"in s.body&&typeof s.body.code=="string"&&"message"in s.body&&typeof s.body.message=="string","isAPIErrorResponse"),c=o((s,e,i)=>n(s)?new t(s.statusCode,{code:e,message:s.body.message,details:s.body.details}):a(s)?new t(s.statusCode,{code:e,message:s.body.message,details:s.body.details}):s instanceof Error?new t(500,{code:e,message:i,details:d==="production"?void 0:{message:s.message,stack:s.stack}}):new t(500,{code:e,message:i,details:d==="production"?void 0:JSON.stringify(s,null,2)}),"parseError");export{t as APIError,n as isAPIError,a as isAPIErrorResponse,c as parseError};
2
+ //# sourceMappingURL=errors.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.mjs","sources":["../../src/api/errors.ts"],"sourcesContent":["import type { StatusCode } from './status-codes';\n\nconst { NODE_ENV } = process.env;\n\ntype APIErrorResponse = {\n\tok: false;\n\tstatusCode: StatusCode;\n\tbody: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t};\n\theaders?: HeadersInit;\n};\n\ntype HeadersInit = Record<string, string> | Array<[string, string]> | Headers;\n\nclass APIError extends Error {\n\treadonly ok = false;\n\treadonly statusCode: StatusCode;\n\treadonly headers: HeadersInit;\n\treadonly body: {\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t};\n\n\tconstructor(body: {\n\t\tstatus: StatusCode;\n\t\tcode: string;\n\t\tmessage: string;\n\t\tdetails?: string | Record<string, unknown>;\n\t\theaders?: HeadersInit;\n\t});\n\tconstructor(\n\t\tstatusCode: StatusCode,\n\t\tbody: {\n\t\t\tcode: string;\n\t\t\tmessage: string;\n\t\t\tdetails?: string | Record<string, unknown>;\n\t\t},\n\t\theaders?: HeadersInit\n\t);\n\tconstructor(\n\t\tstatusCodeOrBody:\n\t\t\t| StatusCode\n\t\t\t| {\n\t\t\t\t\tstatus: StatusCode;\n\t\t\t\t\tcode: string;\n\t\t\t\t\tmessage: string;\n\t\t\t\t\tdetails?: string | Record<string, unknown>;\n\t\t\t\t\theaders?: HeadersInit;\n\t\t\t },\n\t\tbody?: {\n\t\t\tcode: string;\n\t\t\tmessage: string;\n\t\t\tdetails?: string | Record<string, unknown>;\n\t\t},\n\t\theaders?: HeadersInit\n\t) {\n\t\tsuper();\n\n\t\tif (typeof statusCodeOrBody === 'object') {\n\t\t\t// Single argument signature\n\t\t\tthis.statusCode = statusCodeOrBody.status;\n\t\t\tthis.headers = statusCodeOrBody.headers ?? {};\n\t\t\tthis.body = {\n\t\t\t\tcode: statusCodeOrBody.code,\n\t\t\t\tmessage: statusCodeOrBody.message,\n\t\t\t\tdetails: statusCodeOrBody.details,\n\t\t\t};\n\t\t} else {\n\t\t\t// Multi-argument signature\n\t\t\tthis.statusCode = statusCodeOrBody;\n\t\t\tthis.headers = headers ?? {};\n\t\t\tthis.body = body || {\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage:\n\t\t\t\t\t'An error occurred, but no additional information is available.',\n\t\t\t};\n\t\t}\n\n\t\tthis.message = `[${this.body.code}]: ${this.body.message}`;\n\t}\n\n\ttoJSON(): APIErrorResponse {\n\t\treturn {\n\t\t\tok: this.ok,\n\t\t\tstatusCode: this.statusCode,\n\t\t\tbody: this.body,\n\t\t\theaders: this.headers,\n\t\t} satisfies APIErrorResponse;\n\t}\n}\n\n//\n// Start Guards\n//\n\ninterface APISuccessResponse<T> {\n\tok: true;\n\tcode: number;\n\tmessage: string | null;\n\tdata: T;\n}\n\nconst isAPIError = (r: unknown): r is APIError => {\n\tif (r instanceof APIError) {\n\t\treturn true;\n\t}\n\n\tif (isAPIErrorResponse(r)) {\n\t\tr = new APIError(r.statusCode, {\n\t\t\tcode: r.body.code,\n\t\t\tmessage: r.body.message,\n\t\t\tdetails: r.body.details,\n\t\t});\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nconst isAPIErrorResponse = (r: unknown): r is APIErrorResponse => {\n\treturn (\n\t\ttypeof r === 'object' &&\n\t\tr !== null &&\n\t\t'ok' in r &&\n\t\tr.ok === false &&\n\t\t'statusCode' in r &&\n\t\ttypeof r.statusCode === 'number' &&\n\t\t'body' in r &&\n\t\ttypeof r.body === 'object' &&\n\t\tr.body !== null &&\n\t\t'code' in r.body &&\n\t\ttypeof r.body.code === 'string' &&\n\t\t'message' in r.body &&\n\t\ttypeof r.body.message === 'string'\n\t);\n};\n\n/**\n * Parses an unknown error into a standardized APIError. The provided code and message\n * will be used for the resulting APIError, while details from the original error\n * will be included when not in production mode.\n */\nconst parseError = (\n\terror: unknown,\n\tcode: string,\n\tmessage: string\n): APIError => {\n\tif (isAPIError(error)) {\n\t\treturn new APIError(error.statusCode, {\n\t\t\tcode,\n\t\t\tmessage: error.body.message,\n\t\t\tdetails: error.body.details,\n\t\t});\n\t}\n\n\tif (isAPIErrorResponse(error)) {\n\t\treturn new APIError(error.statusCode, {\n\t\t\tcode,\n\t\t\tmessage: error.body.message,\n\t\t\tdetails: error.body.details,\n\t\t});\n\t}\n\n\tif (error instanceof Error) {\n\t\treturn new APIError(500, {\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tdetails:\n\t\t\t\tNODE_ENV === 'production'\n\t\t\t\t\t? undefined\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\t\tstack: error.stack,\n\t\t\t\t\t\t},\n\t\t});\n\t}\n\n\treturn new APIError(500, {\n\t\tcode,\n\t\tmessage,\n\t\tdetails:\n\t\t\tNODE_ENV === 'production' ? undefined : JSON.stringify(error, null, 2),\n\t});\n};\n\nexport {\n\tAPIError,\n\ttype APIErrorResponse,\n\ttype APISuccessResponse,\n\tisAPIError,\n\tisAPIErrorResponse,\n\tparseError,\n};\n"],"names":["NODE_ENV","APIError","__name","statusCodeOrBody","body","headers","isAPIError","r","isAPIErrorResponse","parseError","error","code","message"],"mappings":"+EAEA,KAAM,CAAE,SAAAA,CAAA,EAAa,QAAQ,IAe7B,MAAMC,UAAiB,KAAM,CAf7B,MAe6B,CAAAC,EAAA,iBACnB,GAAK,GACL,WACA,QACA,KAsBT,YACCC,EASAC,EAKAC,EACC,CACD,MAAA,EAEI,OAAOF,GAAqB,UAE/B,KAAK,WAAaA,EAAiB,OACnC,KAAK,QAAUA,EAAiB,SAAW,CAAA,EAC3C,KAAK,KAAO,CACX,KAAMA,EAAiB,KACvB,QAASA,EAAiB,QAC1B,QAASA,EAAiB,OAAA,IAI3B,KAAK,WAAaA,EAClB,KAAK,QAAUE,GAAW,CAAA,EAC1B,KAAK,KAAOD,GAAQ,CACnB,KAAM,wBACN,QACC,gEAAA,GAIH,KAAK,QAAU,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,EACzD,CAEA,QAA2B,CAC1B,MAAO,CACN,GAAI,KAAK,GACT,WAAY,KAAK,WACjB,KAAM,KAAK,KACX,QAAS,KAAK,OAAA,CAEhB,CACD,CAaA,MAAME,EAAaJ,EAACK,GACfA,aAAaN,EACT,GAGJO,EAAmBD,CAAC,GACvBA,EAAI,IAAIN,EAASM,EAAE,WAAY,CAC9B,KAAMA,EAAE,KAAK,KACb,QAASA,EAAE,KAAK,QAChB,QAASA,EAAE,KAAK,OAAA,CAChB,EACM,IAGD,GAdW,cAiBbC,EAAqBN,EAACK,GAE1B,OAAOA,GAAM,UACbA,IAAM,MACN,OAAQA,GACRA,EAAE,KAAO,IACT,eAAgBA,GAChB,OAAOA,EAAE,YAAe,UACxB,SAAUA,GACV,OAAOA,EAAE,MAAS,UAClBA,EAAE,OAAS,MACX,SAAUA,EAAE,MACZ,OAAOA,EAAE,KAAK,MAAS,UACvB,YAAaA,EAAE,MACf,OAAOA,EAAE,KAAK,SAAY,SAdD,sBAuBrBE,EAAaP,EAAA,CAClBQ,EACAC,EACAC,IAEIN,EAAWI,CAAK,EACZ,IAAIT,EAASS,EAAM,WAAY,CACrC,KAAAC,EACA,QAASD,EAAM,KAAK,QACpB,QAASA,EAAM,KAAK,OAAA,CACpB,EAGEF,EAAmBE,CAAK,EACpB,IAAIT,EAASS,EAAM,WAAY,CACrC,KAAAC,EACA,QAASD,EAAM,KAAK,QACpB,QAASA,EAAM,KAAK,OAAA,CACpB,EAGEA,aAAiB,MACb,IAAIT,EAAS,IAAK,CACxB,KAAAU,EACA,QAAAC,EACA,QACCZ,IAAa,aACV,OACA,CACA,QAASU,EAAM,QACf,MAAOA,EAAM,KAAA,CACd,CACH,EAGK,IAAIT,EAAS,IAAK,CACxB,KAAAU,EACA,QAAAC,EACA,QACCZ,IAAa,aAAe,OAAY,KAAK,UAAUU,EAAO,KAAM,CAAC,CAAA,CACtE,EAxCiB"}
@@ -0,0 +1,2 @@
1
+ "use strict";var r=require("./errors.cjs"),s=require("./status-codes.cjs");exports.APIError=r.APIError,exports.isAPIError=r.isAPIError,exports.isAPIErrorResponse=r.isAPIErrorResponse,exports.parseError=r.parseError,exports.isStatusCodeText=s.isStatusCodeText,exports.resolveStatusCode=s.resolveStatusCode,exports.statusCodes=s.statusCodes;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export { APIError, APIErrorResponse, APISuccessResponse, isAPIError, isAPIErrorResponse, parseError } from './errors.cjs';
2
+ export { MinimalNextFunction, MinimalRequest, MinimalRequestHandler, MinimalResponse, Params, ParamsDictionary, ParamsFlatDictionary } from './requests.cjs';
3
+ export { StatusCode, StatusCodeText, isStatusCodeText, resolveStatusCode, statusCodes } from './status-codes.cjs';
4
+ import 'qs';
@@ -0,0 +1,4 @@
1
+ export { APIError, APIErrorResponse, APISuccessResponse, isAPIError, isAPIErrorResponse, parseError } from './errors.mjs';
2
+ export { MinimalNextFunction, MinimalRequest, MinimalRequestHandler, MinimalResponse, Params, ParamsDictionary, ParamsFlatDictionary } from './requests.mjs';
3
+ export { StatusCode, StatusCodeText, isStatusCodeText, resolveStatusCode, statusCodes } from './status-codes.mjs';
4
+ import 'qs';
@@ -0,0 +1,2 @@
1
+ import{APIError as s,isAPIError as e,isAPIErrorResponse as t,parseError as a}from"./errors.mjs";import{isStatusCodeText as E,resolveStatusCode as d,statusCodes as i}from"./status-codes.mjs";export{s as APIError,e as isAPIError,t as isAPIErrorResponse,E as isStatusCodeText,a as parseError,d as resolveStatusCode,i as statusCodes};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { ParsedQs } from 'qs';
2
+
3
+ interface ParamsDictionary {
4
+ [key: string]: string | string[];
5
+ [key: number]: string;
6
+ }
7
+ interface ParamsFlatDictionary {
8
+ [key: string | number]: string;
9
+ }
10
+ type Params = Record<string, string | string[]> | ParamsDictionary | ParamsFlatDictionary;
11
+ interface MinimalRequest {
12
+ protocol: string;
13
+ headers: Record<string, string | string[] | undefined>;
14
+ get(header: string): string | undefined;
15
+ originalUrl?: string;
16
+ params?: Params;
17
+ query?: string | ParsedQs | (string | ParsedQs)[] | undefined;
18
+ body?: Record<string, unknown>;
19
+ ip: string | undefined;
20
+ connection?: {
21
+ remoteAddress?: string;
22
+ };
23
+ }
24
+ interface MinimalResponse {
25
+ locals: Record<string, unknown>;
26
+ statusCode: number;
27
+ setHeader(name: string, value: string): void;
28
+ status(code: number): MinimalResponse;
29
+ send(...args: unknown[]): void;
30
+ json(data: unknown): void;
31
+ end(...args: unknown[]): void;
32
+ }
33
+ type MinimalNextFunction = (err?: unknown) => void;
34
+ type MinimalRequestHandler = (req: MinimalRequest, res: MinimalResponse, next: MinimalNextFunction) => Promise<void> | void;
35
+
36
+ export type { MinimalNextFunction, MinimalRequest, MinimalRequestHandler, MinimalResponse, Params, ParamsDictionary, ParamsFlatDictionary };
@@ -0,0 +1,36 @@
1
+ import { ParsedQs } from 'qs';
2
+
3
+ interface ParamsDictionary {
4
+ [key: string]: string | string[];
5
+ [key: number]: string;
6
+ }
7
+ interface ParamsFlatDictionary {
8
+ [key: string | number]: string;
9
+ }
10
+ type Params = Record<string, string | string[]> | ParamsDictionary | ParamsFlatDictionary;
11
+ interface MinimalRequest {
12
+ protocol: string;
13
+ headers: Record<string, string | string[] | undefined>;
14
+ get(header: string): string | undefined;
15
+ originalUrl?: string;
16
+ params?: Params;
17
+ query?: string | ParsedQs | (string | ParsedQs)[] | undefined;
18
+ body?: Record<string, unknown>;
19
+ ip: string | undefined;
20
+ connection?: {
21
+ remoteAddress?: string;
22
+ };
23
+ }
24
+ interface MinimalResponse {
25
+ locals: Record<string, unknown>;
26
+ statusCode: number;
27
+ setHeader(name: string, value: string): void;
28
+ status(code: number): MinimalResponse;
29
+ send(...args: unknown[]): void;
30
+ json(data: unknown): void;
31
+ end(...args: unknown[]): void;
32
+ }
33
+ type MinimalNextFunction = (err?: unknown) => void;
34
+ type MinimalRequestHandler = (req: MinimalRequest, res: MinimalResponse, next: MinimalNextFunction) => Promise<void> | void;
35
+
36
+ export type { MinimalNextFunction, MinimalRequest, MinimalRequestHandler, MinimalResponse, Params, ParamsDictionary, ParamsFlatDictionary };
@@ -0,0 +1,2 @@
1
+ "use strict";var _=Object.defineProperty;var O=(E,R)=>_(E,"name",{value:R,configurable:!0});const T={CONTINUE:100,SWITCHING_PROTOCOLS:101,PROCESSING:102,EARLY_HINTS:103,OK:200,CREATED:201,ACCEPTED:202,NON_AUTHORITATIVE_INFORMATION:203,NO_CONTENT:204,RESET_CONTENT:205,PARTIAL_CONTENT:206,MULTI_STATUS:207,ALREADY_REPORTED:208,IM_USED:226,MULTIPLE_CHOICES:300,MOVED_PERMANENTLY:301,FOUND:302,SEE_OTHER:303,NOT_MODIFIED:304,USE_PROXY:305,UNUSED:306,TEMPORARY_REDIRECT:307,PERMANENT_REDIRECT:308,BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,PROXY_AUTHENTICATION_REQUIRED:407,REQUEST_TIMEOUT:408,CONFLICT:409,GONE:410,LENGTH_REQUIRED:411,PRECONDITION_FAILED:412,PAYLOAD_TOO_LARGE:413,URI_TOO_LONG:414,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,EXPECTATION_FAILED:417,"I'M_A_TEAPOT":418,MISDIRECTED_REQUEST:421,UNPROCESSABLE_ENTITY:422,LOCKED:423,FAILED_DEPENDENCY:424,TOO_EARLY:425,UPGRADE_REQUIRED:426,PRECONDITION_REQUIRED:428,TOO_MANY_REQUESTS:429,REQUEST_HEADER_FIELDS_TOO_LARGE:431,UNAVAILABLE_FOR_LEGAL_REASONS:451,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504,HTTP_VERSION_NOT_SUPPORTED:505,VARIANT_ALSO_NEGOTIATES:506,INSUFFICIENT_STORAGE:507,LOOP_DETECTED:508,NOT_EXTENDED:510,NETWORK_AUTHENTICATION_REQUIRED:511},N=O(E=>typeof E=="string"&&E in T,"isStatusCodeText"),A=O(E=>typeof E=="number"?E:T[E]??T.INTERNAL_SERVER_ERROR,"resolveStatusCode");exports.isStatusCodeText=N,exports.resolveStatusCode=A,exports.statusCodes=T;
2
+ //# sourceMappingURL=status-codes.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-codes.cjs","sources":["../../src/api/status-codes.ts"],"sourcesContent":["const statusCodes = {\n\t// 1xx Informational\n\tCONTINUE: 100,\n\tSWITCHING_PROTOCOLS: 101,\n\tPROCESSING: 102,\n\tEARLY_HINTS: 103,\n\n\t// 2xx Success\n\tOK: 200,\n\tCREATED: 201,\n\tACCEPTED: 202,\n\tNON_AUTHORITATIVE_INFORMATION: 203,\n\tNO_CONTENT: 204,\n\tRESET_CONTENT: 205,\n\tPARTIAL_CONTENT: 206,\n\tMULTI_STATUS: 207,\n\tALREADY_REPORTED: 208,\n\tIM_USED: 226,\n\n\t// 3xx Redirection\n\tMULTIPLE_CHOICES: 300,\n\tMOVED_PERMANENTLY: 301,\n\tFOUND: 302,\n\tSEE_OTHER: 303,\n\tNOT_MODIFIED: 304,\n\tUSE_PROXY: 305,\n\tUNUSED: 306,\n\tTEMPORARY_REDIRECT: 307,\n\tPERMANENT_REDIRECT: 308,\n\n\t// 4xx Client Errors\n\tBAD_REQUEST: 400,\n\tUNAUTHORIZED: 401,\n\tPAYMENT_REQUIRED: 402,\n\tFORBIDDEN: 403,\n\tNOT_FOUND: 404,\n\tMETHOD_NOT_ALLOWED: 405,\n\tNOT_ACCEPTABLE: 406,\n\tPROXY_AUTHENTICATION_REQUIRED: 407,\n\tREQUEST_TIMEOUT: 408,\n\tCONFLICT: 409,\n\tGONE: 410,\n\tLENGTH_REQUIRED: 411,\n\tPRECONDITION_FAILED: 412,\n\tPAYLOAD_TOO_LARGE: 413,\n\tURI_TOO_LONG: 414,\n\tUNSUPPORTED_MEDIA_TYPE: 415,\n\tRANGE_NOT_SATISFIABLE: 416,\n\tEXPECTATION_FAILED: 417,\n\t\"I'M_A_TEAPOT\": 418,\n\tMISDIRECTED_REQUEST: 421,\n\tUNPROCESSABLE_ENTITY: 422,\n\tLOCKED: 423,\n\tFAILED_DEPENDENCY: 424,\n\tTOO_EARLY: 425,\n\tUPGRADE_REQUIRED: 426,\n\tPRECONDITION_REQUIRED: 428,\n\tTOO_MANY_REQUESTS: 429,\n\tREQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n\tUNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\n\t// 5xx Server Errors\n\tINTERNAL_SERVER_ERROR: 500,\n\tNOT_IMPLEMENTED: 501,\n\tBAD_GATEWAY: 502,\n\tSERVICE_UNAVAILABLE: 503,\n\tGATEWAY_TIMEOUT: 504,\n\tHTTP_VERSION_NOT_SUPPORTED: 505,\n\tVARIANT_ALSO_NEGOTIATES: 506,\n\tINSUFFICIENT_STORAGE: 507,\n\tLOOP_DETECTED: 508,\n\tNOT_EXTENDED: 510,\n\tNETWORK_AUTHENTICATION_REQUIRED: 511,\n} as const;\n\ntype StatusCodeText = keyof typeof statusCodes;\ntype StatusCode = (typeof statusCodes)[StatusCodeText];\n\nconst isStatusCodeText = (value: unknown): value is StatusCodeText => {\n\treturn typeof value === 'string' && value in statusCodes;\n};\n\nconst resolveStatusCode = (status: StatusCodeText | StatusCode): StatusCode => {\n\tif (typeof status === 'number') {\n\t\treturn status;\n\t}\n\n\treturn statusCodes[status] ?? statusCodes.INTERNAL_SERVER_ERROR;\n};\n\nexport {\n\tstatusCodes,\n\ttype StatusCode,\n\ttype StatusCodeText,\n\tisStatusCodeText,\n\tresolveStatusCode,\n};\n"],"names":["statusCodes","isStatusCodeText","__name","value","resolveStatusCode","status"],"mappings":"4FAAA,MAAMA,EAAc,CAEnB,SAAU,IACV,oBAAqB,IACrB,WAAY,IACZ,YAAa,IAGb,GAAI,IACJ,QAAS,IACT,SAAU,IACV,8BAA+B,IAC/B,WAAY,IACZ,cAAe,IACf,gBAAiB,IACjB,aAAc,IACd,iBAAkB,IAClB,QAAS,IAGT,iBAAkB,IAClB,kBAAmB,IACnB,MAAO,IACP,UAAW,IACX,aAAc,IACd,UAAW,IACX,OAAQ,IACR,mBAAoB,IACpB,mBAAoB,IAGpB,YAAa,IACb,aAAc,IACd,iBAAkB,IAClB,UAAW,IACX,UAAW,IACX,mBAAoB,IACpB,eAAgB,IAChB,8BAA+B,IAC/B,gBAAiB,IACjB,SAAU,IACV,KAAM,IACN,gBAAiB,IACjB,oBAAqB,IACrB,kBAAmB,IACnB,aAAc,IACd,uBAAwB,IACxB,sBAAuB,IACvB,mBAAoB,IACpB,eAAgB,IAChB,oBAAqB,IACrB,qBAAsB,IACtB,OAAQ,IACR,kBAAmB,IACnB,UAAW,IACX,iBAAkB,IAClB,sBAAuB,IACvB,kBAAmB,IACnB,gCAAiC,IACjC,8BAA+B,IAG/B,sBAAuB,IACvB,gBAAiB,IACjB,YAAa,IACb,oBAAqB,IACrB,gBAAiB,IACjB,2BAA4B,IAC5B,wBAAyB,IACzB,qBAAsB,IACtB,cAAe,IACf,aAAc,IACd,gCAAiC,GAClC,EAKMC,EAAmBC,EAACC,GAClB,OAAOA,GAAU,UAAYA,KAASH,EADrB,oBAInBI,EAAoBF,EAACG,GACtB,OAAOA,GAAW,SACdA,EAGDL,EAAYK,CAAM,GAAKL,EAAY,sBALjB"}