@gravito/mass 3.0.1 → 3.0.3
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/README.md +109 -75
- package/README.zh-TW.md +120 -11
- package/dist/coercion.d.ts +222 -0
- package/dist/errors.d.ts +168 -0
- package/dist/formats.d.ts +97 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +26 -11
- package/dist/openapi.d.ts +214 -0
- package/dist/types.d.ts +50 -0
- package/dist/utils.d.ts +22 -0
- package/dist/validator.d.ts +40 -0
- package/package.json +11 -7
- package/dist/mass/src/index.d.ts +0 -30
- package/dist/mass/src/index.d.ts.map +0 -1
- package/dist/mass/src/validator.d.ts +0 -28
- package/dist/mass/src/validator.d.ts.map +0 -1
- package/dist/photon/src/index.d.ts +0 -21
- package/dist/photon/src/index.d.ts.map +0 -1
- package/dist/photon/src/middleware/binary.d.ts +0 -35
- package/dist/photon/src/middleware/binary.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
|
-
# @gravito/mass
|
|
1
|
+
# @gravito/mass ⚖️
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> High-performance, TypeBox-powered schema validation for Gravito Galaxy Architecture.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@gravito/mass` provides the "weight" of data integrity to your Gravito applications. Built on top of **TypeBox**, it offers ultra-fast runtime validation with full TypeScript type inference, designed to work seamlessly with the **Photon** HTTP engine.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Full TypeScript support**: Type inference without manual typings
|
|
9
|
-
- **Photon integration**: Works seamlessly with Photon validation middleware
|
|
10
|
-
- **Multiple sources**: Validate JSON, query, params, and form data
|
|
7
|
+
## ✨ Key Features
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
- 🚀 **Performance-First**: Built on TypeBox, it generates ultra-fast validators that outperform standard libraries like Zod.
|
|
10
|
+
- 🌌 **Galaxy-Ready**: The "Data Quality Layer" ensuring integrity across all Gravito Satellites and Orbits.
|
|
11
|
+
- 🛡️ **Full Type Safety**: Zero-config type inference—your schemas are your TypeScript types.
|
|
12
|
+
- 📡 **Beam Integration**: Share schemas between backend and frontend for end-to-end type-safe RPC.
|
|
13
|
+
- 🔌 **Photon Integration**: Native middleware for `@gravito/photon` to validate JSON, query, params, and form data.
|
|
14
|
+
- 📦 **Binary (CBOR) Support**: Optimized validation for binary protocols in high-performance microservices.
|
|
15
|
+
|
|
16
|
+
## 🌌 Role in Galaxy Architecture
|
|
17
|
+
|
|
18
|
+
In the **Gravito Galaxy Architecture**, Mass serves as the **Data Quality Layer (Immune System)**.
|
|
19
|
+
|
|
20
|
+
- **Sensing Filter**: Acts as the first line of defense in the `Photon` Sensing Layer, filtering out malformed or malicious data before it reaches your business logic.
|
|
21
|
+
- **Contract Definition**: Provides the shared language (Schemas) used by `Beam` to ensure that Satellites and clients communicate with perfect understanding.
|
|
22
|
+
- **Type Propagation**: Injects strong types from the edge of the network into the deepest parts of your IoC container.
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
graph LR
|
|
26
|
+
Request([Request]) --> Mass{Mass Filter}
|
|
27
|
+
Mass -- "Valid" --> Satellite[Satellite Business Logic]
|
|
28
|
+
Mass -- "Invalid" --> Error[400 Bad Request]
|
|
29
|
+
Satellite -- "Beam RPC" --> Client([Typed Client])
|
|
30
|
+
Mass -.->|Schema| Client
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 📦 Installation
|
|
13
34
|
|
|
14
35
|
```bash
|
|
15
36
|
bun add @gravito/mass
|
|
16
37
|
```
|
|
17
38
|
|
|
18
|
-
## Quick Start
|
|
39
|
+
## 🚀 Quick Start
|
|
19
40
|
|
|
20
|
-
### JSON
|
|
41
|
+
### Basic JSON Validation
|
|
42
|
+
|
|
43
|
+
Define a schema using `Schema` and apply it to your routes using the `validate` middleware.
|
|
21
44
|
|
|
22
45
|
```typescript
|
|
23
46
|
import { Photon } from '@gravito/photon'
|
|
@@ -25,40 +48,39 @@ import { Schema, validate } from '@gravito/mass'
|
|
|
25
48
|
|
|
26
49
|
const app = new Photon()
|
|
27
50
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
51
|
+
const CreateUserSchema = Schema.Object({
|
|
52
|
+
username: Schema.String({ minLength: 3 }),
|
|
53
|
+
email: Schema.String({ format: 'email' }),
|
|
54
|
+
age: Schema.Number({ minimum: 18 })
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
app.post('/users',
|
|
58
|
+
validate('json', CreateUserSchema),
|
|
33
59
|
(c) => {
|
|
34
|
-
|
|
35
|
-
|
|
60
|
+
// Data is fully typed as { username: string; email: string; age: number }
|
|
61
|
+
const user = c.req.valid('json')
|
|
62
|
+
return c.json({ success: true, data: user })
|
|
36
63
|
}
|
|
37
64
|
)
|
|
38
65
|
```
|
|
39
66
|
|
|
40
|
-
###
|
|
67
|
+
### Validating Different Sources
|
|
68
|
+
|
|
69
|
+
Mass can validate data from various parts of the HTTP request:
|
|
41
70
|
|
|
42
71
|
```typescript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
page: Schema.Optional(Schema.Number())
|
|
47
|
-
})),
|
|
72
|
+
// Query Parameters
|
|
73
|
+
app.get('/search',
|
|
74
|
+
validate('query', Schema.Object({ q: Schema.String() })),
|
|
48
75
|
(c) => {
|
|
49
|
-
const { q
|
|
50
|
-
return c.
|
|
76
|
+
const { q } = c.req.valid('query')
|
|
77
|
+
return c.text(`Searching for: ${q}`)
|
|
51
78
|
}
|
|
52
79
|
)
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Route param validation
|
|
56
80
|
|
|
57
|
-
|
|
81
|
+
// URL Parameters
|
|
58
82
|
app.get('/users/:id',
|
|
59
|
-
validate('param', Schema.Object({
|
|
60
|
-
id: Schema.String({ pattern: '^[0-9]+$' })
|
|
61
|
-
})),
|
|
83
|
+
validate('param', Schema.Object({ id: Schema.Number() })),
|
|
62
84
|
(c) => {
|
|
63
85
|
const { id } = c.req.valid('param')
|
|
64
86
|
return c.json({ userId: id })
|
|
@@ -66,65 +88,77 @@ app.get('/users/:id',
|
|
|
66
88
|
)
|
|
67
89
|
```
|
|
68
90
|
|
|
69
|
-
##
|
|
91
|
+
## ⏳ Advanced Patterns
|
|
92
|
+
|
|
93
|
+
### Partial Updates (PATCH)
|
|
70
94
|
|
|
71
|
-
`
|
|
95
|
+
Use the `partial()` utility to make all properties of a schema optional, perfect for update endpoints.
|
|
72
96
|
|
|
73
97
|
```typescript
|
|
74
|
-
import {
|
|
98
|
+
import { partial } from '@gravito/mass'
|
|
75
99
|
|
|
76
|
-
|
|
77
|
-
Schema.Number()
|
|
78
|
-
Schema.Boolean()
|
|
79
|
-
Schema.Array(Schema.String())
|
|
100
|
+
const UpdateUserSchema = partial(CreateUserSchema)
|
|
80
101
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Schema.String({ minLength: 2, maxLength: 100 })
|
|
89
|
-
Schema.Number({ minimum: 0, maximum: 100 })
|
|
90
|
-
Schema.String({ format: 'email' })
|
|
102
|
+
app.patch('/users/:id',
|
|
103
|
+
validate('json', UpdateUserSchema),
|
|
104
|
+
(c) => {
|
|
105
|
+
const updates = c.req.valid('json')
|
|
106
|
+
return c.json({ updated: updates })
|
|
107
|
+
}
|
|
108
|
+
)
|
|
91
109
|
```
|
|
92
110
|
|
|
93
|
-
|
|
111
|
+
### Custom Error Handling
|
|
94
112
|
|
|
95
|
-
|
|
113
|
+
Override the default 400 response with your own error format using the validation hook.
|
|
96
114
|
|
|
97
115
|
```typescript
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
app.post('/strict-endpoint',
|
|
117
|
+
validate('json', schema, (result, c) => {
|
|
118
|
+
if (!result.success) {
|
|
119
|
+
return c.json({
|
|
120
|
+
code: 'VAL_ERR',
|
|
121
|
+
errors: result.errors.map(e => ({ field: e.path, msg: e.message }))
|
|
122
|
+
}, 422)
|
|
123
|
+
}
|
|
124
|
+
}),
|
|
125
|
+
(c) => c.text('Success')
|
|
126
|
+
)
|
|
127
|
+
```
|
|
101
128
|
|
|
102
|
-
|
|
103
|
-
const routes = app.route('/api/users', userRoute)
|
|
129
|
+
## 🧩 API Reference
|
|
104
130
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
131
|
+
### `validate(source, schema, hook?)`
|
|
132
|
+
Main middleware for schema enforcement.
|
|
133
|
+
- `source`: `'json' | 'query' | 'param' | 'form'`
|
|
134
|
+
- `schema`: A TypeBox schema instance.
|
|
135
|
+
- `hook`: `(result, context) => Response | undefined`
|
|
108
136
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
137
|
+
### `Schema`
|
|
138
|
+
The central builder for defining data structures. Re-exports all TypeBox builders.
|
|
139
|
+
- `Schema.String()`
|
|
140
|
+
- `Schema.Number()`
|
|
141
|
+
- `Schema.Boolean()`
|
|
142
|
+
- `Schema.Object({ ... })`
|
|
143
|
+
- `Schema.Array(...)`
|
|
144
|
+
- `Schema.Optional(...)`
|
|
113
145
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
146
|
+
### `partial(schema)`
|
|
147
|
+
Recursively makes all properties in an object schema optional.
|
|
117
148
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
149
|
+
## 📚 Documentation
|
|
150
|
+
|
|
151
|
+
Detailed guides and references for the Galaxy Architecture:
|
|
152
|
+
|
|
153
|
+
- [🏗️ **Architecture Overview**](./README.md) — Data integrity and schema validation.
|
|
154
|
+
- [📐 **Schema Design**](./doc/SCHEMA_DESIGN.md) — **NEW**: Best practices for domain-specific schemas and composition.
|
|
155
|
+
- [🛡️ **Validation Strategy**](./doc/VALIDATION_STRATEGY.md) — **NEW**: Multi-source validation, hooks, and performance tuning.
|
|
156
|
+
- [🔌 **Photon Integration**](#-photon-integration) — Native middleware for request validation.
|
|
123
157
|
|
|
124
|
-
##
|
|
158
|
+
## 🤝 Contributing
|
|
125
159
|
|
|
126
|
-
|
|
160
|
+
We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
|
|
127
161
|
|
|
128
|
-
## License
|
|
162
|
+
## 📄 License
|
|
129
163
|
|
|
130
|
-
MIT
|
|
164
|
+
MIT © Carl Lee
|
package/README.zh-TW.md
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
# @gravito/mass
|
|
1
|
+
# @gravito/mass ⚖️
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 基於 TypeBox 的高效能 Schema 驗證工具,專為 Gravito Galaxy 架構設計。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@gravito/mass` 為您的 Gravito 應用程式提供數據完整性的「重量」。基於 **TypeBox** 構建,它提供了極快的執行期驗證速度與完整的 TypeScript 類型推導,並與 **Photon** HTTP 引擎無縫整合。
|
|
6
|
+
|
|
7
|
+
## 🌟 核心特性
|
|
8
|
+
|
|
9
|
+
- **🚀 效能優先**:利用 TypeBox 的編譯期驗證器生成技術,實現近乎零負擔的執行期效能。
|
|
10
|
+
- **🛡️ 完整類型安全**:自動進行 TypeScript 類型推導 —— 無需分別維護 Interface 與 Schema。
|
|
11
|
+
- **🔌 Photon 深度整合**:提供原生中間件,支援驗證 JSON、Query、URL 參數及表單數據。
|
|
12
|
+
- **🛠️ Schema 實用工具**:提供如 `partial()` 等進階輔助函式,輕鬆建立 PATCH 接口所需的 Schema。
|
|
13
|
+
- **🪝 靈活的 Hook 機制**:可攔截驗證結果,自定義錯誤回應格式或紀錄日誌。
|
|
14
|
+
- **📦 Galaxy 架構相容**:遵循 Gravito 的模組化哲學,保持依賴精簡且高效。
|
|
15
|
+
|
|
16
|
+
## 📦 安裝
|
|
6
17
|
|
|
7
18
|
```bash
|
|
8
19
|
bun add @gravito/mass
|
|
9
20
|
```
|
|
10
21
|
|
|
11
|
-
##
|
|
22
|
+
## 🚀 快速上手
|
|
23
|
+
|
|
24
|
+
### 基礎 JSON 驗證
|
|
25
|
+
|
|
26
|
+
使用 `Schema` 定義數據結構,並透過 `validate` 中間件應用於路由。
|
|
12
27
|
|
|
13
28
|
```typescript
|
|
14
29
|
import { Photon } from '@gravito/photon'
|
|
@@ -16,14 +31,108 @@ import { Schema, validate } from '@gravito/mass'
|
|
|
16
31
|
|
|
17
32
|
const app = new Photon()
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
const CreateUserSchema = Schema.Object({
|
|
35
|
+
username: Schema.String({ minLength: 3 }),
|
|
36
|
+
email: Schema.String({ format: 'email' }),
|
|
37
|
+
age: Schema.Number({ minimum: 18 })
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
app.post('/users',
|
|
41
|
+
validate('json', CreateUserSchema),
|
|
42
|
+
(c) => {
|
|
43
|
+
// 數據已自動推導類型為 { username: string; email: string; age: number }
|
|
44
|
+
const user = c.req.valid('json')
|
|
45
|
+
return c.json({ success: true, data: user })
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 驗證不同數據源
|
|
51
|
+
|
|
52
|
+
Mass 可以驗證 HTTP 請求中不同位置的數據:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// 驗證 Query 參數
|
|
56
|
+
app.get('/search',
|
|
57
|
+
validate('query', Schema.Object({ q: Schema.String() })),
|
|
24
58
|
(c) => {
|
|
25
|
-
const {
|
|
26
|
-
return c.
|
|
59
|
+
const { q } = c.req.valid('query')
|
|
60
|
+
return c.text(`正在搜尋:${q}`)
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
// 驗證 URL 參數
|
|
65
|
+
app.get('/users/:id',
|
|
66
|
+
validate('param', Schema.Object({ id: Schema.Number() })),
|
|
67
|
+
(c) => {
|
|
68
|
+
const { id } = c.req.valid('param')
|
|
69
|
+
return c.json({ userId: id })
|
|
27
70
|
}
|
|
28
71
|
)
|
|
29
72
|
```
|
|
73
|
+
|
|
74
|
+
## ⏳ 進階模式
|
|
75
|
+
|
|
76
|
+
### 部分更新 (PATCH)
|
|
77
|
+
|
|
78
|
+
使用 `partial()` 工具將 Schema 中的所有屬性轉為可選,非常適合用於更新接口。
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { partial } from '@gravito/mass'
|
|
82
|
+
|
|
83
|
+
const UpdateUserSchema = partial(CreateUserSchema)
|
|
84
|
+
|
|
85
|
+
app.patch('/users/:id',
|
|
86
|
+
validate('json', UpdateUserSchema),
|
|
87
|
+
(c) => {
|
|
88
|
+
const updates = c.req.valid('json')
|
|
89
|
+
return c.json({ updated: updates })
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 自定義錯誤處理
|
|
95
|
+
|
|
96
|
+
透過驗證 Hook 覆蓋預設的 400 回應,提供符合您需求的錯誤格式。
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
app.post('/strict-endpoint',
|
|
100
|
+
validate('json', schema, (result, c) => {
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
return c.json({
|
|
103
|
+
code: 'VAL_ERR',
|
|
104
|
+
errors: result.errors.map(e => ({ field: e.path, msg: e.message }))
|
|
105
|
+
}, 422)
|
|
106
|
+
}
|
|
107
|
+
}),
|
|
108
|
+
(c) => c.text('成功')
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 🧩 API 參考
|
|
113
|
+
|
|
114
|
+
### `validate(source, schema, hook?)`
|
|
115
|
+
強制執行 Schema 驗證的主要中間件。
|
|
116
|
+
- `source`: `'json' | 'query' | 'param' | 'form'`
|
|
117
|
+
- `schema`: TypeBox Schema 實例。
|
|
118
|
+
- `hook`: `(result, context) => Response | undefined`
|
|
119
|
+
|
|
120
|
+
### `Schema`
|
|
121
|
+
定義數據結構的核心工具,重新導出了所有 TypeBox 的建構子。
|
|
122
|
+
- `Schema.String()`
|
|
123
|
+
- `Schema.Number()`
|
|
124
|
+
- `Schema.Boolean()`
|
|
125
|
+
- `Schema.Object({ ... })`
|
|
126
|
+
- `Schema.Array(...)`
|
|
127
|
+
- `Schema.Optional(...)`
|
|
128
|
+
|
|
129
|
+
### `partial(schema)`
|
|
130
|
+
遞迴地將物件 Schema 中的所有屬性設為可選。
|
|
131
|
+
|
|
132
|
+
## 🤝 參與貢獻
|
|
133
|
+
|
|
134
|
+
我們歡迎任何形式的貢獻!詳細資訊請參閱 [貢獻指南](../../CONTRIBUTING.md)。
|
|
135
|
+
|
|
136
|
+
## 📄 開源授權
|
|
137
|
+
|
|
138
|
+
MIT © Carl Lee
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { GravitoContext, GravitoMiddleware } from '@gravito/core';
|
|
2
|
+
import type { TBoolean, TInteger, TNumber, TSchema } from '@sinclair/typebox';
|
|
3
|
+
/**
|
|
4
|
+
* String to Number Coercion Helper.
|
|
5
|
+
*
|
|
6
|
+
* Converts a string value from query or params to a JavaScript Number.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The string value to coerce
|
|
9
|
+
* @returns The converted number, or NaN if conversion fails
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* coerceNumber('123') // 123
|
|
14
|
+
* coerceNumber('12.34') // 12.34
|
|
15
|
+
* coerceNumber('abc') // NaN
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function coerceNumber(value: string): number;
|
|
19
|
+
/**
|
|
20
|
+
* String to Integer Coercion Helper.
|
|
21
|
+
*
|
|
22
|
+
* Converts a string value from query or params to a JavaScript Number (Integer).
|
|
23
|
+
*
|
|
24
|
+
* @param value - The string value to coerce
|
|
25
|
+
* @returns The converted integer, or NaN if conversion fails
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* coerceInteger('123') // 123
|
|
30
|
+
* coerceInteger('12.99') // 12
|
|
31
|
+
* coerceInteger('abc') // NaN
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function coerceInteger(value: string): number;
|
|
35
|
+
/**
|
|
36
|
+
* String to Boolean Coercion Helper.
|
|
37
|
+
*
|
|
38
|
+
* Converts a string value from query or params to a JavaScript Boolean.
|
|
39
|
+
* Supports multiple common boolean string representations.
|
|
40
|
+
*
|
|
41
|
+
* @param value - The string value to coerce
|
|
42
|
+
* @returns The converted boolean value
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* coerceBoolean('true') // true
|
|
47
|
+
* coerceBoolean('1') // true
|
|
48
|
+
* coerceBoolean('yes') // true
|
|
49
|
+
* coerceBoolean('false') // false
|
|
50
|
+
* coerceBoolean('0') // false
|
|
51
|
+
* coerceBoolean('no') // false
|
|
52
|
+
* coerceBoolean('') // false
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function coerceBoolean(value: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* String to Date Coercion Helper.
|
|
58
|
+
*
|
|
59
|
+
* Converts a string date (ISO 8601) from query or params to a JavaScript Date object.
|
|
60
|
+
*
|
|
61
|
+
* @param value - The string value (ISO 8601 format)
|
|
62
|
+
* @returns The converted Date object, or Invalid Date if conversion fails
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* coerceDate('2024-01-15') // Date object
|
|
67
|
+
* coerceDate('2024-01-15T10:30:00Z') // Date object
|
|
68
|
+
* coerceDate('invalid') // Invalid Date
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function coerceDate(value: string): Date;
|
|
72
|
+
/**
|
|
73
|
+
* Creates a Number Schema with Automatic Coercion.
|
|
74
|
+
*
|
|
75
|
+
* Builds a TypeBox Number schema that automatically converts string input to number before validation.
|
|
76
|
+
* Suitable for query and param validation where data sources are string-based.
|
|
77
|
+
*
|
|
78
|
+
* @param options - TypeBox Number schema options
|
|
79
|
+
* @returns TypeBox Number schema (with automatic coercion)
|
|
80
|
+
*
|
|
81
|
+
* @example Query Parameter Coercion
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const searchSchema = Schema.Object({
|
|
84
|
+
* page: CoercibleNumber({ minimum: 1, default: 1 }),
|
|
85
|
+
* limit: CoercibleNumber({ minimum: 1, maximum: 100, default: 20 })
|
|
86
|
+
* })
|
|
87
|
+
*
|
|
88
|
+
* app.get('/search', validate('query', searchSchema), (c) => {
|
|
89
|
+
* const { page, limit } = c.req.valid('query')
|
|
90
|
+
* // page and limit are typed as number
|
|
91
|
+
* return c.json({ page, limit })
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function CoercibleNumber(options?: Partial<TNumber['properties']> & {
|
|
96
|
+
default?: number;
|
|
97
|
+
}): TNumber;
|
|
98
|
+
/**
|
|
99
|
+
* Creates an Integer Schema with Automatic Coercion.
|
|
100
|
+
*
|
|
101
|
+
* Builds a TypeBox Integer schema that automatically converts string input to integer before validation.
|
|
102
|
+
*
|
|
103
|
+
* @param options - TypeBox Integer schema options
|
|
104
|
+
* @returns TypeBox Integer schema (with automatic coercion)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const schema = Schema.Object({
|
|
109
|
+
* userId: CoercibleInteger({ minimum: 1 })
|
|
110
|
+
* })
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function CoercibleInteger(options?: Partial<TInteger['properties']> & {
|
|
114
|
+
default?: number;
|
|
115
|
+
}): TInteger;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a Boolean Schema with Automatic Coercion.
|
|
118
|
+
*
|
|
119
|
+
* Builds a TypeBox Boolean schema that automatically converts string input to boolean before validation.
|
|
120
|
+
*
|
|
121
|
+
* @param options - TypeBox Boolean schema options
|
|
122
|
+
* @returns TypeBox Boolean schema (with automatic coercion)
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const schema = Schema.Object({
|
|
127
|
+
* active: CoercibleBoolean({ default: false }),
|
|
128
|
+
* published: CoercibleBoolean()
|
|
129
|
+
* })
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function CoercibleBoolean(options?: Partial<TBoolean['properties']> & {
|
|
133
|
+
default?: boolean;
|
|
134
|
+
}): TBoolean;
|
|
135
|
+
/**
|
|
136
|
+
* Performs Automatic Data Coercion.
|
|
137
|
+
*
|
|
138
|
+
* Traverses the object and automatically converts string data to corresponding types
|
|
139
|
+
* based on the schema definition. Primarily used for pre-processing query and param data.
|
|
140
|
+
*
|
|
141
|
+
* @param data - The raw data object
|
|
142
|
+
* @param schema - The TypeBox schema definition
|
|
143
|
+
* @returns The coerced data object
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const schema = Type.Object({
|
|
148
|
+
* page: Type.Number(),
|
|
149
|
+
* limit: Type.Number(),
|
|
150
|
+
* active: Type.Boolean()
|
|
151
|
+
* })
|
|
152
|
+
*
|
|
153
|
+
* const raw = { page: '1', limit: '20', active: 'true' }
|
|
154
|
+
* const coerced = coerceData(raw, schema)
|
|
155
|
+
* // { page: 1, limit: 20, active: true }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function coerceData<T extends TSchema>(data: unknown, schema: T): unknown;
|
|
159
|
+
/**
|
|
160
|
+
* Creates Validation Middleware with Automatic Coercion.
|
|
161
|
+
*
|
|
162
|
+
* Extends the standard validate middleware to automatically convert string data to appropriate
|
|
163
|
+
* types before validation. Especially useful for query and param validation where data sources
|
|
164
|
+
* are string-based.
|
|
165
|
+
*
|
|
166
|
+
* @template T - TypeBox schema type
|
|
167
|
+
*
|
|
168
|
+
* @param source - Validation source (recommend using 'query' or 'param')
|
|
169
|
+
* @param schema - TypeBox schema definition
|
|
170
|
+
* @param hook - Optional validation result hook
|
|
171
|
+
* @returns Gravito middleware handler
|
|
172
|
+
*
|
|
173
|
+
* @example Query Parameter Coercion
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const searchSchema = Type.Object({
|
|
176
|
+
* page: Type.Number({ minimum: 1 }),
|
|
177
|
+
* limit: Type.Number({ minimum: 1, maximum: 100 }),
|
|
178
|
+
* active: Type.Optional(Type.Boolean())
|
|
179
|
+
* })
|
|
180
|
+
*
|
|
181
|
+
* app.get('/search',
|
|
182
|
+
* validateWithCoercion('query', searchSchema),
|
|
183
|
+
* (c) => {
|
|
184
|
+
* const { page, limit, active } = c.req.valid('query')
|
|
185
|
+
* // All values are automatically coerced to correct types
|
|
186
|
+
* return c.json({ page, limit, active })
|
|
187
|
+
* }
|
|
188
|
+
* )
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @example Route Parameter Coercion
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const paramSchema = Type.Object({
|
|
194
|
+
* id: Type.Number({ minimum: 1 })
|
|
195
|
+
* })
|
|
196
|
+
*
|
|
197
|
+
* app.get('/users/:id',
|
|
198
|
+
* validateWithCoercion('param', paramSchema),
|
|
199
|
+
* (c) => {
|
|
200
|
+
* const { id } = c.req.valid('param')
|
|
201
|
+
* // id converted from string to number
|
|
202
|
+
* return c.json({ userId: id })
|
|
203
|
+
* }
|
|
204
|
+
* )
|
|
205
|
+
* ```
|
|
206
|
+
*
|
|
207
|
+
* @example With Custom Error Handling
|
|
208
|
+
* ```typescript
|
|
209
|
+
* app.get('/items',
|
|
210
|
+
* validateWithCoercion('query', querySchema, (result, c) => {
|
|
211
|
+
* if (!result.success) {
|
|
212
|
+
* return c.json({
|
|
213
|
+
* error: 'Invalid query parameters',
|
|
214
|
+
* details: result.errors
|
|
215
|
+
* }, 400)
|
|
216
|
+
* }
|
|
217
|
+
* }),
|
|
218
|
+
* handler
|
|
219
|
+
* )
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export declare function validateWithCoercion<T extends TSchema>(source: 'json' | 'query' | 'param' | 'form', schema: T, hook?: (result: unknown, c: GravitoContext) => Response | Promise<Response> | undefined): GravitoMiddleware;
|