exisjs 0.7.3 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/generate.d.ts +4 -0
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +227 -14
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/index.js +8 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/config/config.js +1 -1
- package/dist/config/config.js.map +1 -1
- package/dist/database/index.d.ts +4 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +20 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/lifecycle.d.ts +52 -0
- package/dist/database/lifecycle.d.ts.map +1 -0
- package/dist/database/lifecycle.js +122 -0
- package/dist/database/lifecycle.js.map +1 -0
- package/dist/database/mongoose.d.ts +47 -0
- package/dist/database/mongoose.d.ts.map +1 -0
- package/dist/database/mongoose.js +44 -0
- package/dist/database/mongoose.js.map +1 -0
- package/dist/database/transaction.d.ts +39 -0
- package/dist/database/transaction.d.ts.map +1 -0
- package/dist/database/transaction.js +99 -0
- package/dist/database/transaction.js.map +1 -0
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +1 -0
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/middleware.d.ts +10 -0
- package/dist/decorators/middleware.d.ts.map +1 -1
- package/dist/decorators/middleware.js +27 -0
- package/dist/decorators/middleware.js.map +1 -1
- package/dist/decorators/upload.d.ts +37 -0
- package/dist/decorators/upload.d.ts.map +1 -0
- package/dist/decorators/upload.js +78 -0
- package/dist/decorators/upload.js.map +1 -0
- package/dist/docs/content/cli/commands.mdx +4 -3
- package/dist/docs/content/config.mdx +1 -1
- package/dist/docs/content/errors.mdx +43 -9
- package/dist/docs/content/middleware.mdx +138 -0
- package/dist/docs/content/providers.mdx +89 -0
- package/dist/docs/content/requests.mdx +153 -64
- package/dist/docs/content/responses.mdx +56 -1
- package/dist/docs/content/routing.mdx +117 -0
- package/dist/docs/content/validation.mdx +92 -7
- package/dist/docs/reference/database.mdx +152 -0
- package/dist/docs/reference/decorators.mdx +4 -0
- package/dist/docs/reference/error.mdx +3 -1
- package/dist/docs/reference/middleware.mdx +84 -2
- package/dist/docs/reference/router.mdx +4 -2
- package/dist/docs/reference/validator.mdx +43 -5
- package/dist/error/errors.d.ts +10 -0
- package/dist/error/errors.d.ts.map +1 -1
- package/dist/error/errors.js +156 -25
- package/dist/error/errors.js.map +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.d.ts.map +1 -1
- package/dist/error/index.js +3 -1
- package/dist/error/index.js.map +1 -1
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +18 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/middleware.d.ts +13 -0
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/middleware.js +22 -2
- package/dist/middleware/middleware.js.map +1 -1
- package/dist/middleware/security.d.ts +13 -3
- package/dist/middleware/security.d.ts.map +1 -1
- package/dist/middleware/security.js +98 -14
- package/dist/middleware/security.js.map +1 -1
- package/dist/middleware/upload.d.ts +82 -0
- package/dist/middleware/upload.d.ts.map +1 -0
- package/dist/middleware/upload.js +387 -0
- package/dist/middleware/upload.js.map +1 -0
- package/dist/router/index.d.ts +3 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +6 -1
- package/dist/router/index.js.map +1 -1
- package/dist/router/route-builder.d.ts +11 -2
- package/dist/router/route-builder.d.ts.map +1 -1
- package/dist/router/route-builder.js.map +1 -1
- package/dist/router/route-scanner.d.ts.map +1 -1
- package/dist/router/route-scanner.js +26 -0
- package/dist/router/route-scanner.js.map +1 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +58 -2
- package/dist/router/router.js.map +1 -1
- package/dist/router/types.d.ts +30 -0
- package/dist/router/types.d.ts.map +1 -1
- package/dist/server/request.d.ts +5 -0
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +32 -4
- package/dist/server/request.js.map +1 -1
- package/dist/testing/mocks.d.ts +3 -1
- package/dist/testing/mocks.d.ts.map +1 -1
- package/dist/testing/mocks.js +7 -1
- package/dist/testing/mocks.js.map +1 -1
- package/dist/validator/index.d.ts +1 -1
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +3 -1
- package/dist/validator/index.js.map +1 -1
- package/dist/validator/tex-types.d.ts +5 -1
- package/dist/validator/tex-types.d.ts.map +1 -1
- package/dist/validator/tex-types.js +4 -0
- package/dist/validator/tex-types.js.map +1 -1
- package/dist/validator/tex.d.ts +38 -0
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js +126 -17
- package/dist/validator/tex.js.map +1 -1
- package/package.json +5 -1
|
@@ -452,6 +452,123 @@ export default class SearchController {
|
|
|
452
452
|
|
|
453
453
|
|
|
454
454
|
|
|
455
|
+
## Declarative Route Options (Uploads, Timeouts & Validation)
|
|
456
|
+
|
|
457
|
+
ExisJS allows configuring input validation schemas, multipart file uploads, and per-route timeouts directly inside the route definition without manual middleware plumbing.
|
|
458
|
+
|
|
459
|
+
### Declarative File Uploads
|
|
460
|
+
|
|
461
|
+
Specify `upload` in your route definition to automatically handle `multipart/form-data`. Uploaded files are parsed and attached to `req.file` or `req.files`, while non-file form fields are populated in `req.body`.
|
|
462
|
+
|
|
463
|
+
#### Functional Paradigm
|
|
464
|
+
```typescript filename="src/http/avatar/route.ts"
|
|
465
|
+
import { controller, route } from 'exisjs/router'
|
|
466
|
+
import { tex } from 'exisjs/validator'
|
|
467
|
+
|
|
468
|
+
export default controller({
|
|
469
|
+
uploadAvatar: route.post('/', {
|
|
470
|
+
upload: {
|
|
471
|
+
field: 'avatar',
|
|
472
|
+
maxBytes: 5 * 1024 * 1024, // 5MB limit
|
|
473
|
+
mimeTypes: ['image/png', 'image/jpeg', 'image/webp'],
|
|
474
|
+
},
|
|
475
|
+
body: tex.object({
|
|
476
|
+
caption: tex.string({ optional: true }),
|
|
477
|
+
}),
|
|
478
|
+
handle({ req }) {
|
|
479
|
+
const file = req.file! // UploadedFile { filename, buffer, size, mimetype }
|
|
480
|
+
const caption = req.body?.caption
|
|
481
|
+
|
|
482
|
+
return {
|
|
483
|
+
success: true,
|
|
484
|
+
filename: file.filename,
|
|
485
|
+
size: file.size,
|
|
486
|
+
caption,
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
})
|
|
490
|
+
})
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Class-Based (OOP) Paradigm
|
|
494
|
+
```typescript filename="src/http/avatar/route.ts"
|
|
495
|
+
import { Controller, Post, Body } from 'exisjs/decorators'
|
|
496
|
+
import { Upload, UploadedFile } from 'exisjs/decorators'
|
|
497
|
+
import type { UploadedFile as UploadedFileType } from 'exisjs/middleware'
|
|
498
|
+
|
|
499
|
+
@Controller('/avatar')
|
|
500
|
+
export default class AvatarController {
|
|
501
|
+
@Post('/')
|
|
502
|
+
@Upload('avatar', {
|
|
503
|
+
maxBytes: 5 * 1024 * 1024,
|
|
504
|
+
mimeTypes: ['image/png', 'image/jpeg', 'image/webp'],
|
|
505
|
+
})
|
|
506
|
+
upload(
|
|
507
|
+
@UploadedFile() file: UploadedFileType,
|
|
508
|
+
@Body('caption') caption?: string
|
|
509
|
+
) {
|
|
510
|
+
return {
|
|
511
|
+
success: true,
|
|
512
|
+
filename: file.filename,
|
|
513
|
+
size: file.size,
|
|
514
|
+
caption,
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Route-Level Timeout Overrides
|
|
521
|
+
|
|
522
|
+
While ExisJS provides a generous 60-second default global timeout, long-running batch jobs, PDF generation, or third-party AI integrations can override the timeout at the individual route level:
|
|
523
|
+
|
|
524
|
+
#### Functional Paradigm
|
|
525
|
+
```typescript filename="src/http/reports/route.ts"
|
|
526
|
+
import { controller, route } from 'exisjs/router'
|
|
527
|
+
|
|
528
|
+
export default controller({
|
|
529
|
+
generateAnnualReport: route.post('/annual', {
|
|
530
|
+
timeout: 120000, // 2 minutes specifically for this route
|
|
531
|
+
async handle() {
|
|
532
|
+
// Intensive document rendering or AI workflow
|
|
533
|
+
const reportUrl = await buildReport()
|
|
534
|
+
return { success: true, reportUrl }
|
|
535
|
+
}
|
|
536
|
+
})
|
|
537
|
+
})
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Query Pagination Schemas
|
|
541
|
+
|
|
542
|
+
ExisJS provides the `tex.pagination()` primitive for declarative pagination, sorting, and ordering query parameters. String query parameters are automatically coerced into numbers:
|
|
543
|
+
|
|
544
|
+
```typescript filename="src/http/products/route.ts"
|
|
545
|
+
import { controller, route } from 'exisjs/router'
|
|
546
|
+
import { tex, paginate, getPaginationSkip } from 'exisjs/validator'
|
|
547
|
+
|
|
548
|
+
const ProductQuerySchema = tex.pagination({
|
|
549
|
+
defaultLimit: 20,
|
|
550
|
+
maxLimit: 100,
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
export default controller({
|
|
554
|
+
list: route.get('/', {
|
|
555
|
+
query: ProductQuerySchema,
|
|
556
|
+
async handle({ query }) {
|
|
557
|
+
// query.page and query.limit are guaranteed positive numbers
|
|
558
|
+
const { skip, limit, page } = getPaginationSkip(query)
|
|
559
|
+
|
|
560
|
+
// Fetch data using your preferred database query
|
|
561
|
+
const [items, total] = await Promise.all([
|
|
562
|
+
db.products.findMany({ skip, take: limit }),
|
|
563
|
+
db.products.count()
|
|
564
|
+
])
|
|
565
|
+
|
|
566
|
+
return paginate(items, total, { page, limit })
|
|
567
|
+
}
|
|
568
|
+
})
|
|
569
|
+
})
|
|
570
|
+
```
|
|
571
|
+
|
|
455
572
|
## Dependency Injection in Functional Controllers
|
|
456
573
|
|
|
457
574
|
ExisJS natively supports **Request-Scoped Dependency Injection** directly inside functional routes. You don't need to use classes to get the benefits of DI!
|
|
@@ -38,11 +38,17 @@ ExisJS supports a comprehensive set of strict validation primitives:
|
|
|
38
38
|
- `tex.boolean()` - Strict boolean validation.
|
|
39
39
|
- `tex.number({ coerce: true })` - Automatically coerces incoming string representations into native JavaScript numbers.
|
|
40
40
|
- `tex.boolean({ coerce: true })` - Coerces `"true"`/`"1"` and `"false"`/`"0"` into native booleans.
|
|
41
|
-
- `tex.array(schema)` - Validates an array of items.
|
|
41
|
+
- `tex.array(schema)` - Validates an array of items. Accepts primitive types, `tex.object(...)`, or shorthand plain objects `{ ... }`.
|
|
42
42
|
- `tex.object({ ... })` - Validates structured JSON objects.
|
|
43
43
|
- `tex.enum(['A', 'B'])` - Ensures the value matches one of the provided exact strings.
|
|
44
44
|
|
|
45
|
-
All primitives accept
|
|
45
|
+
All primitives accept modifier options or chained helper methods:
|
|
46
|
+
- `.optional()` / `{ optional: true }` - Allows `undefined`.
|
|
47
|
+
- `.nullable()` / `{ nullable: true }` - Allows `null`.
|
|
48
|
+
- `.nullish()` / `{ nullish: true }` - Allows both `null` and `undefined`.
|
|
49
|
+
|
|
50
|
+
> [!TIP]
|
|
51
|
+
> **Automatic Empty String `""` Normalization**: When forms or query parameters pass empty strings `""` for fields marked as `.optional()`, `.nullable()`, or `.nullish()`, ExisJS automatically converts them to `undefined` or `null` before running type validation. This prevents false positive type errors on numeric, UUID, or enum fields!
|
|
46
52
|
|
|
47
53
|
### Data Sanitization (Trimming & Formatting)
|
|
48
54
|
|
|
@@ -217,16 +223,95 @@ export default class BooksController {
|
|
|
217
223
|
```
|
|
218
224
|
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
### Nested Sub-Documents & Array Schemas
|
|
227
|
+
|
|
228
|
+
ExisJS natively validates arbitrarily deep sub-documents and nested arrays off-heap with Rust acceleration:
|
|
229
|
+
|
|
230
|
+
```typescript filename="src/http/users/schema.ts"
|
|
231
|
+
import { tex } from 'exisjs/validator'
|
|
232
|
+
|
|
233
|
+
export const RegisterUserSchema = tex.object({
|
|
234
|
+
username: tex.string({ min: 3 }),
|
|
235
|
+
profile: tex.object({
|
|
236
|
+
bio: tex.string().nullish(), // allows undefined, null, or ""
|
|
237
|
+
avatarUrl: tex.string({ optional: true }),
|
|
238
|
+
socials: tex.object({
|
|
239
|
+
twitter: tex.string({ optional: true }),
|
|
240
|
+
github: tex.string({ optional: true }),
|
|
241
|
+
}),
|
|
242
|
+
tags: tex.array(tex.string({ min: 2 })),
|
|
243
|
+
}),
|
|
244
|
+
// You can use tex.object(...) OR a plain object schema shorthand!
|
|
245
|
+
items: tex.array({
|
|
246
|
+
sku: tex.string(),
|
|
247
|
+
quantity: tex.number({ min: 1 }),
|
|
248
|
+
}),
|
|
249
|
+
})
|
|
250
|
+
```
|
|
221
251
|
|
|
222
|
-
|
|
252
|
+
#### First-Class Form & Multipart Support
|
|
253
|
+
- **Single-Object Coercion**: When HTML forms or mobile clients submit a single item instead of an array (e.g. `{ items: { sku: "ABC", quantity: 1 } }`), the Rust engine automatically coerces it into a single-element array `[ { sku: "ABC", quantity: 1 } ]` rather than throwing `"Must be an array"`.
|
|
254
|
+
- **Stringified JSON Support**: When submitting `multipart/form-data`, stringified JSON arrays (e.g. `items: "[{\"sku\":\"ABC\",\"quantity\":2}]"`) or stringified objects are automatically deserialized and validated.
|
|
255
|
+
- **Type Inference**: TypeScript automatically infers the shape of array elements for both `tex.array(tex.object(...))` and `tex.array({ ... })`, ensuring full autocomplete without falling back to `never`.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Pagination Schemas (`tex.pagination`)
|
|
260
|
+
|
|
261
|
+
ExisJS provides a dedicated schema primitive for query pagination. It automatically coerces incoming string query parameters (`?page=2&limit=25&sort=name&order=asc`) into typed numbers and strings while enforcing sensible bounds:
|
|
262
|
+
|
|
263
|
+
```typescript filename="src/http/items/route.ts"
|
|
264
|
+
import { controller, route } from 'exisjs/router'
|
|
265
|
+
import { tex, paginate, getPaginationSkip } from 'exisjs/validator'
|
|
266
|
+
|
|
267
|
+
const ItemQuerySchema = tex.pagination({
|
|
268
|
+
defaultLimit: 20, // Default items per page if omitted
|
|
269
|
+
maxLimit: 100, // Hard cap to prevent memory exhaustion
|
|
270
|
+
})
|
|
223
271
|
|
|
224
|
-
|
|
272
|
+
export default controller({
|
|
273
|
+
list: route.get('/', {
|
|
274
|
+
query: ItemQuerySchema,
|
|
275
|
+
async handle({ query }) {
|
|
276
|
+
const { skip, limit, page } = getPaginationSkip(query)
|
|
277
|
+
const items = await fetchItems({ skip, limit, sort: query.sort, order: query.order })
|
|
278
|
+
const total = await countItems()
|
|
279
|
+
|
|
280
|
+
return paginate(items, total, { page, limit })
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Error Handling & Developer Diagnostics
|
|
289
|
+
|
|
290
|
+
If a request fails validation, ExisJS intercepts the rejection and returns a standardized `400 Bad Request` containing a machine-readable `errors: Record<string, string>` dictionary for frontend form field mapping:
|
|
291
|
+
|
|
292
|
+
```json filename="HTTP 400 Bad Request Response"
|
|
225
293
|
{
|
|
226
294
|
"statusCode": 400,
|
|
227
295
|
"error": "Bad Request",
|
|
228
|
-
"message": "Validation Error:
|
|
296
|
+
"message": "Validation Error: username: Field must be at least 4 characters, profile.tags: Expected array of strings",
|
|
297
|
+
"errors": {
|
|
298
|
+
"username": "Field must be at least 4 characters",
|
|
299
|
+
"profile.tags": "Expected array of strings"
|
|
300
|
+
}
|
|
229
301
|
}
|
|
230
302
|
```
|
|
231
303
|
|
|
232
|
-
|
|
304
|
+
### Dev Mode Terminal Diagnostics
|
|
305
|
+
|
|
306
|
+
When validation fails in development mode, ExisJS prints an immediate tabular diagnostic to your terminal displaying the failing HTTP part, exact field path, received value, and expected schema constraint:
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
[VALIDATION FAILED] POST /visits (part: body)
|
|
310
|
+
┌─────────────┬───────────────────────────┬──────────────────┐
|
|
311
|
+
│ Field │ Received │ Expected │
|
|
312
|
+
├─────────────┼───────────────────────────┼──────────────────┤
|
|
313
|
+
│ phone │ "123" │ min: 7, max: 20 │
|
|
314
|
+
│ idProofs │ "[object Object]" │ Array of IDProof │
|
|
315
|
+
└─────────────┴───────────────────────────┴──────────────────┘
|
|
316
|
+
```
|
|
317
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Database"
|
|
3
|
+
description: "API Reference for ExisJS Database Lifecycle & Transactions (exisjs/database)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Database (`exisjs/database`)
|
|
7
|
+
|
|
8
|
+
ExisJS provides a unified, database-agnostic lifecycle and transaction layer. It enables automatic connection management, multi-database health checks, graceful zero-downtime teardowns, and ORM-agnostic transaction runners.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Lifecycle Management
|
|
13
|
+
|
|
14
|
+
### `registerDatabase(app, options)`
|
|
15
|
+
|
|
16
|
+
Registers a database connection into the application lifecycle. Automatically calls `connect()` during server boot and `disconnect()` during graceful shutdown (`SIGTERM`, `SIGINT`, or `app.close()`).
|
|
17
|
+
|
|
18
|
+
#### Options (`DatabaseRegistrationOptions`)
|
|
19
|
+
- `name` (`string`): Unique identifier for the database connection (e.g. `'postgres'`, `'mongodb'`).
|
|
20
|
+
- `connect` (`() => Promise<void>`): Async callback to establish connection and connection pools.
|
|
21
|
+
- `disconnect` (`() => Promise<void>`): Async callback to close connections gracefully.
|
|
22
|
+
- `healthCheck` (`() => Promise<boolean>`): Optional health check callback returning `true` when healthy.
|
|
23
|
+
|
|
24
|
+
```typescript filename="src/http/server.ts"
|
|
25
|
+
import { exis } from 'exisjs'
|
|
26
|
+
import { registerDatabase } from 'exisjs/database'
|
|
27
|
+
import { PrismaClient } from '@prisma/client'
|
|
28
|
+
|
|
29
|
+
const prisma = new PrismaClient()
|
|
30
|
+
|
|
31
|
+
export default exis({
|
|
32
|
+
async onStart(app) {
|
|
33
|
+
registerDatabase(app, {
|
|
34
|
+
name: 'prisma-postgres',
|
|
35
|
+
connect: async () => {
|
|
36
|
+
await prisma.$connect()
|
|
37
|
+
},
|
|
38
|
+
disconnect: async () => {
|
|
39
|
+
await prisma.$disconnect()
|
|
40
|
+
},
|
|
41
|
+
healthCheck: async () => {
|
|
42
|
+
await prisma.$queryRaw`SELECT 1`
|
|
43
|
+
return true
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### `DatabaseManager`
|
|
53
|
+
|
|
54
|
+
Singleton registry managing all registered database adapters.
|
|
55
|
+
|
|
56
|
+
- `DatabaseManager.register(options)`: Registers a database adapter.
|
|
57
|
+
- `DatabaseManager.connectAll()`: Connects all registered databases concurrently.
|
|
58
|
+
- `DatabaseManager.disconnectAll()`: Gracefully disconnects all databases concurrently.
|
|
59
|
+
- `DatabaseManager.checkHealth()`: Runs health checks across all registered databases and returns `{ healthy: boolean, databases: Record<string, boolean> }`.
|
|
60
|
+
- `DatabaseManager.clear()`: Clears all registered database adapters (useful for test tear-downs).
|
|
61
|
+
|
|
62
|
+
```typescript filename="src/http/health/route.ts"
|
|
63
|
+
import { controller, route } from 'exisjs/router'
|
|
64
|
+
import { DatabaseManager } from 'exisjs/database'
|
|
65
|
+
|
|
66
|
+
export default controller({
|
|
67
|
+
check: route.get('/health', async () => {
|
|
68
|
+
const health = await DatabaseManager.checkHealth()
|
|
69
|
+
return {
|
|
70
|
+
status: health.healthy ? 'ok' : 'degraded',
|
|
71
|
+
databases: health.databases,
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 2. Universal Transaction Runner
|
|
80
|
+
|
|
81
|
+
### `withTransaction(client, callback)`
|
|
82
|
+
|
|
83
|
+
A duck-typed transaction runner that coordinates database transaction lifecycles, commits, rollbacks, and session cleanups. Compatible with **Mongoose**, **Prisma**, and **Drizzle**.
|
|
84
|
+
|
|
85
|
+
```typescript filename="src/services/transfer.ts"
|
|
86
|
+
import { withTransaction } from 'exisjs/database'
|
|
87
|
+
import mongoose from 'mongoose'
|
|
88
|
+
import { Account } from '@/models/Account'
|
|
89
|
+
|
|
90
|
+
export async function transferFunds(fromId: string, toId: string, amount: number) {
|
|
91
|
+
return withTransaction(mongoose, async (session) => {
|
|
92
|
+
// Session is automatically attached to MongoDB queries
|
|
93
|
+
const sender = await Account.findByIdAndUpdate(
|
|
94
|
+
fromId,
|
|
95
|
+
{ $inc: { balance: -amount } },
|
|
96
|
+
{ session, returnDocument: 'after' }
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if (!sender || sender.balance < 0) {
|
|
100
|
+
// Throwing an error automatically aborts the transaction and rolls back
|
|
101
|
+
throw new Error('Insufficient funds')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const receiver = await Account.findByIdAndUpdate(
|
|
105
|
+
toId,
|
|
106
|
+
{ $inc: { balance: amount } },
|
|
107
|
+
{ session, returnDocument: 'after' }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return { sender, receiver }
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Works identically with Prisma:
|
|
116
|
+
```typescript
|
|
117
|
+
import { withTransaction } from 'exisjs/database'
|
|
118
|
+
import { prisma } from '@/lib/prisma'
|
|
119
|
+
|
|
120
|
+
const result = await withTransaction(prisma, async (tx) => {
|
|
121
|
+
return tx.user.create({ data: { name: 'Alice' } })
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 3. Mongoose 8/9 Interop & Pooling
|
|
128
|
+
|
|
129
|
+
### `modernUpdateOptions(options?)`
|
|
130
|
+
|
|
131
|
+
Maps deprecated Mongoose options (such as `{ new: true }`) to standard modern options (`{ returnDocument: 'after' }`), eliminating console warnings when upgrading to Mongoose 8 and 9.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { modernUpdateOptions } from 'exisjs/database'
|
|
135
|
+
|
|
136
|
+
// Passes { returnDocument: 'after' } warning-free
|
|
137
|
+
User.findByIdAndUpdate(id, { $set: updateData }, modernUpdateOptions())
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `mongoPoolOptions(customOptions?)`
|
|
141
|
+
|
|
142
|
+
Returns pre-configured, production-hardened MongoDB connection pool settings:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { mongoPoolOptions } from 'exisjs/database'
|
|
146
|
+
import mongoose from 'mongoose'
|
|
147
|
+
|
|
148
|
+
await mongoose.connect(process.env.MONGODB_URI!, mongoPoolOptions({
|
|
149
|
+
maxPoolSize: 100,
|
|
150
|
+
minPoolSize: 10,
|
|
151
|
+
}))
|
|
152
|
+
```
|
|
@@ -68,6 +68,8 @@ Parameter decorators automatically extract data from the incoming request and in
|
|
|
68
68
|
- `@Param(nameOrPipe?)`: Injects a URL path parameter (e.g., `id` from `/:id`).
|
|
69
69
|
- `@Headers(nameOrPipe?)`: Injects an HTTP header by name.
|
|
70
70
|
- `@QueryParam(nameOrPipe?)` / `@Query(nameOrPipe?)`: Injects a URL query parameter (e.g., `?search=term`).
|
|
71
|
+
- `@UploadedFile()`: Injects the uploaded file (`req.file`) into the method argument.
|
|
72
|
+
- `@UploadedFiles()`: Injects the uploaded files array or dictionary (`req.files`) into the method argument.
|
|
71
73
|
- `@HostParam(nameOrPipe?)`: Injects a subdomain parameter.
|
|
72
74
|
- `@Req()`: Injects the raw ExisJS Request object.
|
|
73
75
|
- `@Res(options?)`: Injects the raw ExisJS Response object (`{ passthrough: true }`).
|
|
@@ -80,6 +82,8 @@ Parameter decorators automatically extract data from the incoming request and in
|
|
|
80
82
|
## 3. Middleware & Pipeline Decorators
|
|
81
83
|
|
|
82
84
|
- `@Use(...middlewaresOrGuardsOrInterceptorsOrFilters)`: Unified decorator that binds middlewares, guards (`canActivate`), interceptors (`intercept`), or exception filters (`catch`) to a controller class or method.
|
|
85
|
+
- `@Upload(fieldName, options?)` / `@UseUpload(...)`: Configures multipart file upload handling for a method, populating `@UploadedFile()` or `@UploadedFiles()`.
|
|
86
|
+
- `@Timeout(ms: number | TimeoutOptions)`: Overrides the request timeout for this method (e.g. `@Timeout(120000)`). Passing `0` disables timeouts for long-running streaming or exports.
|
|
83
87
|
- `@Idempotent(options?)`: Caches responses based on the `Idempotency-Key` header using native in-memory off-heap storage.
|
|
84
88
|
|
|
85
89
|
---
|
|
@@ -61,6 +61,7 @@ export default controller({
|
|
|
61
61
|
- `HttpError.forbidden(msg?)` (403)
|
|
62
62
|
- `HttpError.notFound(resource?)` (404)
|
|
63
63
|
- `HttpError.conflict(msg)` (409)
|
|
64
|
+
- `HttpError.payloadTooLarge(msg?)` (413)
|
|
64
65
|
- `HttpError.unprocessable(msg, details?)` (422)
|
|
65
66
|
- `HttpError.tooManyRequests(msg?)` (429)
|
|
66
67
|
- `HttpError.internal(msg?)` (500)
|
|
@@ -83,7 +84,7 @@ If you catch an `HttpError` or intercept it, you have access to the following pr
|
|
|
83
84
|
If you prefer class instantiation (common in NestJS workflows), you can directly instantiate the error classes or their `Exception` aliases.
|
|
84
85
|
|
|
85
86
|
```typescript filename="src/services/auth.ts"
|
|
86
|
-
import { UnauthorizedError, ConflictException } from 'exisjs/error'
|
|
87
|
+
import { UnauthorizedError, ConflictException, PayloadTooLargeError } from 'exisjs/error'
|
|
87
88
|
|
|
88
89
|
export function verifyToken(token: string) {
|
|
89
90
|
if (!isValid(token)) {
|
|
@@ -104,6 +105,7 @@ export function createUser(email: string) {
|
|
|
104
105
|
- `ForbiddenError` / `ForbiddenException`
|
|
105
106
|
- `NotFoundError` / `NotFoundException`
|
|
106
107
|
- `ConflictError` / `ConflictException`
|
|
108
|
+
- `PayloadTooLargeError` / `PayloadTooLargeException`
|
|
107
109
|
- `UnprocessableError` / `UnprocessableException`
|
|
108
110
|
- `RateLimitError` / `RateLimitException`
|
|
109
111
|
- `InternalError` / `InternalException`
|
|
@@ -62,8 +62,67 @@ app.use(helmet())
|
|
|
62
62
|
### `csrf(options)`
|
|
63
63
|
Implements the Signed Double Submit Cookie pattern for Cross-Site Request Forgery (CSRF) protection.
|
|
64
64
|
|
|
65
|
-
### `timeout(
|
|
66
|
-
Automatically times out requests that exceed the specified
|
|
65
|
+
### `timeout(options?)`
|
|
66
|
+
Automatically times out requests that exceed the specified duration, returning a `503 Service Unavailable` response (or custom status code).
|
|
67
|
+
|
|
68
|
+
- **Default**: `60000` (60 seconds)
|
|
69
|
+
- **Options**:
|
|
70
|
+
- `ms` (`number`): Timeout duration in milliseconds.
|
|
71
|
+
- `statusCode` (`number`): Status code to respond with (default: `503`).
|
|
72
|
+
- `message` (`string`): Error message returned to the client.
|
|
73
|
+
- `exclude` (`(string | RegExp)[]`): Array of route paths or regex patterns to exempt from timeout checks.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { timeout } from 'exisjs/middleware'
|
|
77
|
+
|
|
78
|
+
app.use(timeout({
|
|
79
|
+
ms: 60000,
|
|
80
|
+
exclude: ['/webhooks/*', '/ai/stream'],
|
|
81
|
+
}))
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Handlers can dynamically alter the active timeout using `req.setTimeout(ms)` or `req.clearTimeout()`.
|
|
85
|
+
|
|
86
|
+
### `fileUpload(options?)`
|
|
87
|
+
First-party multipart form data parsing and file upload middleware.
|
|
88
|
+
|
|
89
|
+
- **Methods**:
|
|
90
|
+
- `fileUpload.single(fieldName, options?)`: Parses a single file into `req.file`.
|
|
91
|
+
- `fileUpload.array(fieldName, maxCount?, options?)`: Parses multiple files with the same field into `req.files` (`UploadedFile[]`).
|
|
92
|
+
- `fileUpload.fields([{ name, maxCount }])`: Parses multiple distinct fields into `req.files` (`Record<string, UploadedFile[]>`).
|
|
93
|
+
- `fileUpload.any(options?)`: Accepts any uploaded files.
|
|
94
|
+
- `fileUpload.none(options?)`: Accepts only text fields; rejects file uploads.
|
|
95
|
+
- **Options**:
|
|
96
|
+
- `dest` (`string`): Directory path to save uploaded files to disk automatically.
|
|
97
|
+
- `maxBytes` (`number`): Maximum file size in bytes (shorthand for `limits.fileSize`).
|
|
98
|
+
- `mimeTypes` (`string[]`): Array of permitted MIME types (e.g. `['image/png', 'image/jpeg']`).
|
|
99
|
+
- `limits` (`{ fileSize?: number; files?: number }`): Detailed size and count limits.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { fileUpload } from 'exisjs/middleware'
|
|
103
|
+
|
|
104
|
+
app.post('/avatar', fileUpload.single('avatar', {
|
|
105
|
+
maxBytes: 5 * 1024 * 1024,
|
|
106
|
+
mimeTypes: ['image/*'],
|
|
107
|
+
}), (req, res) => {
|
|
108
|
+
const file = req.file // UploadedFile { filename, originalname, mimetype, size, buffer }
|
|
109
|
+
res.json({ success: true, filename: file.filename })
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `fromExpress(middleware)`
|
|
114
|
+
Seamlessly adapts standard Express/Connect middleware (such as `multer`) to run within the ExisJS pipeline.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { fromExpress } from 'exisjs/middleware'
|
|
118
|
+
import multer from 'multer'
|
|
119
|
+
|
|
120
|
+
const upload = multer({ dest: './uploads' })
|
|
121
|
+
|
|
122
|
+
app.post('/upload', fromExpress(upload.single('file')), (req, res) => {
|
|
123
|
+
res.json({ file: (req.raw as any).file })
|
|
124
|
+
})
|
|
125
|
+
```
|
|
67
126
|
|
|
68
127
|
### `hpp()`
|
|
69
128
|
HTTP Parameter Pollution protection.
|
|
@@ -90,6 +149,29 @@ app.use(rateLimit({
|
|
|
90
149
|
}))
|
|
91
150
|
```
|
|
92
151
|
|
|
152
|
+
### `timeout(options?)`
|
|
153
|
+
Terminates long-running requests that exceed the specified threshold, responding with `503 Service Unavailable` (or custom status). Defaults to 60,000ms.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { timeout } from 'exisjs/middleware'
|
|
157
|
+
|
|
158
|
+
app.use(timeout({
|
|
159
|
+
ms: 60000,
|
|
160
|
+
statusCode: 504,
|
|
161
|
+
message: 'Gateway Timeout',
|
|
162
|
+
exclude: ['/webhooks/*', '/ai/stream'],
|
|
163
|
+
}))
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `routeTimeout(msOrOptions)`
|
|
167
|
+
Applies an endpoint-specific timeout. If a global timeout is already active, dynamically overrides the timer for this route. If no global timeout exists, initializes an isolated timeout timer. Passing `0` disables timeouts for streaming/exports.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { routeTimeout } from 'exisjs/middleware'
|
|
171
|
+
|
|
172
|
+
app.post('/heavy-task', routeTimeout(120000), (req, res) => { ... })
|
|
173
|
+
```
|
|
174
|
+
|
|
93
175
|
### `idempotent(options?)`
|
|
94
176
|
Caches responses based on the `Idempotency-Key` header into off-heap native memory to prevent duplicate mutations.
|
|
95
177
|
|
|
@@ -78,9 +78,11 @@ export default controller({
|
|
|
78
78
|
|
|
79
79
|
### Options (`RouteConfig`)
|
|
80
80
|
|
|
81
|
-
- `body`: A validation schema for the request body (e.g., using `
|
|
82
|
-
- `query`: A validation schema for the query string.
|
|
81
|
+
- `body`: A validation schema for the request body (e.g., using `tex` or Zod).
|
|
82
|
+
- `query`: A validation schema for the query string (e.g., `tex.pagination()`).
|
|
83
83
|
- `params`: A validation schema for the URL path parameters.
|
|
84
|
+
- `upload` (`string | RouteUploadOptions`): Declarative multipart upload configuration (e.g. `{ field: 'photo', maxBytes: 10 * 1024 * 1024, mimeTypes: [...] }`). Automatically mounts `fileUpload` middleware and populates `req.file` / `req.files`.
|
|
85
|
+
- `timeout` (`number`): Per-route timeout override in milliseconds (e.g. `120000`). Overrides global timeout for this endpoint.
|
|
84
86
|
- `response`: A validation schema to serialize/validate the outgoing response.
|
|
85
87
|
- `middleware` (`Handler[]`): An array of middleware specific to this route.
|
|
86
88
|
- `cors` (`boolean | CorsConfig`): Route-specific CORS overrides.
|
|
@@ -21,17 +21,50 @@ The `tex` object provides factory functions for every common primitive and data
|
|
|
21
21
|
|
|
22
22
|
### Objects & Arrays
|
|
23
23
|
|
|
24
|
-
- `tex.object({ ... })`: Validates an object against a strict shape.
|
|
25
|
-
- `tex.array(schema)`: Validates an array of items matching the given schema.
|
|
24
|
+
- `tex.object({ ... })`: Validates an object against a strict shape. Supports arbitrarily nested sub-documents (`tex.object({ nested: tex.object(...) })`).
|
|
25
|
+
- `tex.array(schema, options?)`: Validates an array of items matching the given schema.
|
|
26
|
+
- **Schema Types**: Accepts primitive types (`tex.string()`), nested `tex.object(...)`, or shorthand plain objects (`tex.array({ ... })`).
|
|
27
|
+
- **TypeScript Inference**: TypeScript automatically infers the element object shape for both `tex.object(...)` and plain objects without falling back to `never`.
|
|
28
|
+
- **Single-Object Coercion**: Automatically coerces single objects (e.g. `{ item: { ... } }` from HTML forms) into single-item arrays `[ { ... } ]` rather than throwing `"Must be an array"`.
|
|
29
|
+
- **Stringified JSON**: Automatically parses and deserializes stringified JSON arrays (e.g. from `multipart/form-data`).
|
|
30
|
+
- **Options**: Supports `{ min, max, dedupe, optional, nullable, nullish }`.
|
|
26
31
|
|
|
27
32
|
```typescript
|
|
28
33
|
const UserProfile = tex.object({
|
|
29
34
|
id: tex.string(),
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
profile: tex.object({
|
|
36
|
+
bio: tex.string().nullish(), // allows undefined, null, or ""
|
|
37
|
+
skills: tex.array(tex.string()),
|
|
38
|
+
}),
|
|
39
|
+
// Can use plain object shorthand directly inside tex.array
|
|
40
|
+
items: tex.array({
|
|
41
|
+
id: tex.string(),
|
|
42
|
+
quantity: tex.number({ min: 1 }),
|
|
43
|
+
}),
|
|
44
|
+
role: tex.enum(['admin', 'user']),
|
|
32
45
|
})
|
|
33
46
|
```
|
|
34
47
|
|
|
48
|
+
### Pagination Primitive (`tex.pagination`)
|
|
49
|
+
|
|
50
|
+
- `tex.pagination(options?)`: Pre-compiled query schema validating `page` (default 1), `limit` (with coercion and clamping), `sort`, and `order` (`asc` | `desc`).
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { tex, paginate, getPaginationSkip } from 'exisjs/validator'
|
|
54
|
+
|
|
55
|
+
const paginationSchema = tex.pagination({
|
|
56
|
+
defaultLimit: 20,
|
|
57
|
+
maxLimit: 100,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Database offset calculation helper
|
|
61
|
+
const { skip, limit, page } = getPaginationSkip({ page: 2, limit: 20 })
|
|
62
|
+
// skip = 20, limit = 20, page = 2
|
|
63
|
+
|
|
64
|
+
// Standardized envelope builder
|
|
65
|
+
const paginatedResponse = paginate(items, 150, { page: 2, limit: 20 })
|
|
66
|
+
```
|
|
67
|
+
|
|
35
68
|
---
|
|
36
69
|
|
|
37
70
|
## Usage in Routes
|
|
@@ -78,9 +111,14 @@ export default controller({
|
|
|
78
111
|
|
|
79
112
|
All validators accept an options object that allows you to configure validation constraints and behaviors.
|
|
80
113
|
|
|
81
|
-
- `optional`: Marks the field as optional (allows `undefined`).
|
|
114
|
+
- `optional` / `.optional()`: Marks the field as optional (allows `undefined`).
|
|
115
|
+
- `nullable` / `.nullable()`: Marks the field as nullable (allows `null`).
|
|
116
|
+
- `nullish` / `.nullish()`: Marks the field as nullish (allows both `null` and `undefined`).
|
|
82
117
|
- `coerce`: Instructs the Rust engine to automatically convert types when possible before validating. For example, converting `"123"` into a number, or `3000` into a string.
|
|
83
118
|
|
|
119
|
+
> [!NOTE]
|
|
120
|
+
> **Empty String Interop**: If an incoming string is empty (`""`), and the field is configured as `optional`, `nullable`, or `nullish`, ExisJS automatically converts it to `undefined` or `null` before running type checks. This cleanly handles form submissions and query strings without requiring ad-hoc pre-processors.
|
|
121
|
+
|
|
84
122
|
```typescript
|
|
85
123
|
// Type Conversion Examples using { coerce: true }
|
|
86
124
|
const EnvSchema = tex.object({
|
package/dist/error/errors.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare class HttpError extends Error {
|
|
|
11
11
|
static notFound(resource?: string): HttpError;
|
|
12
12
|
static conflict(message: string): HttpError;
|
|
13
13
|
static unprocessable(message: string, details?: unknown): HttpError;
|
|
14
|
+
static payloadTooLarge(message?: string, details?: unknown): HttpError;
|
|
14
15
|
static tooManyRequests(message?: string): HttpError;
|
|
15
16
|
static internal(message?: string): HttpError;
|
|
16
17
|
static serviceUnavailable(message?: string): HttpError;
|
|
@@ -35,6 +36,9 @@ export declare class ConflictError extends HttpError {
|
|
|
35
36
|
export declare class UnprocessableError extends HttpError {
|
|
36
37
|
constructor(message?: string, details?: unknown);
|
|
37
38
|
}
|
|
39
|
+
export declare class PayloadTooLargeError extends HttpError {
|
|
40
|
+
constructor(message?: string, details?: unknown);
|
|
41
|
+
}
|
|
38
42
|
export declare class RateLimitError extends HttpError {
|
|
39
43
|
constructor(message?: string);
|
|
40
44
|
}
|
|
@@ -53,11 +57,17 @@ export declare const UnauthorizedException: typeof UnauthorizedError;
|
|
|
53
57
|
export declare const ForbiddenException: typeof ForbiddenError;
|
|
54
58
|
export declare const NotFoundException: typeof NotFoundError;
|
|
55
59
|
export declare const ConflictException: typeof ConflictError;
|
|
60
|
+
export declare const PayloadTooLargeException: typeof PayloadTooLargeError;
|
|
56
61
|
export declare const UnprocessableException: typeof UnprocessableError;
|
|
57
62
|
export declare const RateLimitException: typeof RateLimitError;
|
|
58
63
|
export declare const InternalException: typeof InternalError;
|
|
59
64
|
export declare const ServiceUnavailableException: typeof ServiceUnavailableError;
|
|
60
65
|
export declare const GatewayTimeoutException: typeof GatewayTimeoutError;
|
|
66
|
+
export declare function renderValidationTable(rows: {
|
|
67
|
+
field: string;
|
|
68
|
+
received: string;
|
|
69
|
+
expected: string;
|
|
70
|
+
}[]): string;
|
|
61
71
|
export declare function createErrorHandler(isDev?: boolean): ErrorHandler;
|
|
62
72
|
/**
|
|
63
73
|
* Async handler wrapper — catches promise rejections.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/error/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAKrD,qBAAa,SAAU,SAAQ,KAAK;IAClC,SAAgB,UAAU,EAAE,MAAM,CAAA;IAClC,SAAgB,IAAI,EAAE,MAAM,CAAA;IAC5B,SAAgB,aAAa,EAAE,OAAO,CAAA;IACtC,SAAgB,OAAO,CAAC,EAAE,OAAO,CAAA;gBAG/B,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,EAChB,IAAI,SAAmB,EACvB,OAAO,CAAC,EAAE,OAAO;IAenB,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS;IAIhE,MAAM,CAAC,YAAY,CAAC,OAAO,SAAiB,GAAG,SAAS;IAIxD,MAAM,CAAC,SAAS,CAAC,OAAO,SAAc,GAAG,SAAS;IAIlD,MAAM,CAAC,QAAQ,CAAC,QAAQ,SAAa,GAAG,SAAS;IAIjD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS;IAI3C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS;IAInE,MAAM,CAAC,eAAe,CAAC,OAAO,SAAsB,GAAG,SAAS;IAIhE,MAAM,CAAC,QAAQ,CAAC,OAAO,SAA0B,GAAG,SAAS;IAI7D,MAAM,CAAC,kBAAkB,CAAC,OAAO,SAAwB,GAAG,SAAS;IAIrE,MAAM,CAAC,cAAc,CAAC,OAAO,SAAoB,GAAG,SAAS;IAI7D,MAAM,IAAI,MAAM;CAUjB;AAED,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,OAAO,SAAgB,EAAE,OAAO,CAAC,EAAE,OAAO;CAIvD;AAED,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,SAAiB;CAIrC;AAED,qBAAa,cAAe,SAAQ,SAAS;gBAC/B,OAAO,SAAc;CAIlC;AAED,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,QAAQ,SAAa;CAIlC;AAED,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,SAAa;CAIjC;AAED,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,SAAyB,EAAE,OAAO,CAAC,EAAE,OAAO;CAIhE;AAED,qBAAa,cAAe,SAAQ,SAAS;gBAC/B,OAAO,SAAsB;CAI1C;AAED,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,SAA0B;CAI9C;AAED,qBAAa,uBAAwB,SAAQ,SAAS;gBACxC,OAAO,SAAwB;CAI5C;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,SAAoB;CAIxC;AAGD,eAAO,MAAM,aAAa,kBAAY,CAAA;AACtC,eAAO,MAAM,mBAAmB,wBAAkB,CAAA;AAClD,eAAO,MAAM,qBAAqB,0BAAoB,CAAA;AACtD,eAAO,MAAM,kBAAkB,uBAAiB,CAAA;AAChD,eAAO,MAAM,iBAAiB,sBAAgB,CAAA;AAC9C,eAAO,MAAM,iBAAiB,sBAAgB,CAAA;AAC9C,eAAO,MAAM,sBAAsB,2BAAqB,CAAA;AACxD,eAAO,MAAM,kBAAkB,uBAAiB,CAAA;AAChD,eAAO,MAAM,iBAAiB,sBAAgB,CAAA;AAC9C,eAAO,MAAM,2BAA2B,gCAA0B,CAAA;AAClE,eAAO,MAAM,uBAAuB,4BAAsB,CAAA;AA6G1D,wBAAgB,kBAAkB,CAAC,KAAK,UAAQ,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/error/errors.ts"],"names":[],"mappings":"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"}
|