@gravito/mass 3.0.0 → 3.0.2

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 CHANGED
@@ -1,23 +1,29 @@
1
- # @gravito/mass
1
+ # @gravito/mass ⚖️
2
2
 
3
- TypeBox-based validation for Gravito. High-performance schema validation with full TypeScript support.
3
+ > High-performance, TypeBox-powered schema validation for Gravito Galaxy Architecture.
4
4
 
5
- ## Features
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
- - **Fast validation**: TypeBox-powered validators with strong runtime performance
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
- ## Installation
9
+ - **🚀 Performance-First**: Leverages TypeBox's build-time validator generation for near-zero runtime overhead.
10
+ - **🛡️ Full Type Safety**: Automatic TypeScript type inference—no need to manually maintain interfaces and schemas separately.
11
+ - **🔌 Photon Integration**: Native middleware for `@gravito/photon` to validate JSON, query, params, and form data.
12
+ - **🛠️ Schema Utilities**: Advanced helpers like `partial()` for easy creation of PATCH schemas.
13
+ - **🪝 Extensible Hooks**: Intercept validation results to provide custom error responses or logging.
14
+ - **📦 Galaxy-Ready**: Follows Gravito's modular philosophy for lean, efficient dependency management.
15
+
16
+ ## 📦 Installation
13
17
 
14
18
  ```bash
15
19
  bun add @gravito/mass
16
20
  ```
17
21
 
18
- ## Quick Start
22
+ ## 🚀 Quick Start
23
+
24
+ ### Basic JSON Validation
19
25
 
20
- ### JSON validation
26
+ Define a schema using `Schema` and apply it to your routes using the `validate` middleware.
21
27
 
22
28
  ```typescript
23
29
  import { Photon } from '@gravito/photon'
@@ -25,40 +31,39 @@ import { Schema, validate } from '@gravito/mass'
25
31
 
26
32
  const app = new Photon()
27
33
 
28
- app.post('/login',
29
- validate('json', Schema.Object({
30
- username: Schema.String(),
31
- password: Schema.String()
32
- })),
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),
33
42
  (c) => {
34
- const { username } = c.req.valid('json')
35
- return c.json({ success: true, message: `Welcome ${username}` })
43
+ // Data is fully typed as { username: string; email: string; age: number }
44
+ const user = c.req.valid('json')
45
+ return c.json({ success: true, data: user })
36
46
  }
37
47
  )
38
48
  ```
39
49
 
40
- ### Query validation
50
+ ### Validating Different Sources
51
+
52
+ Mass can validate data from various parts of the HTTP request:
41
53
 
42
54
  ```typescript
43
- app.get('/search',
44
- validate('query', Schema.Object({
45
- q: Schema.String(),
46
- page: Schema.Optional(Schema.Number())
47
- })),
55
+ // Query Parameters
56
+ app.get('/search',
57
+ validate('query', Schema.Object({ q: Schema.String() })),
48
58
  (c) => {
49
- const { q, page } = c.req.valid('query')
50
- return c.json({ query: q, page: page ?? 1 })
59
+ const { q } = c.req.valid('query')
60
+ return c.text(`Searching for: ${q}`)
51
61
  }
52
62
  )
53
- ```
54
63
 
55
- ### Route param validation
56
-
57
- ```typescript
64
+ // URL Parameters
58
65
  app.get('/users/:id',
59
- validate('param', Schema.Object({
60
- id: Schema.String({ pattern: '^[0-9]+$' })
61
- })),
66
+ validate('param', Schema.Object({ id: Schema.Number() })),
62
67
  (c) => {
63
68
  const { id } = c.req.valid('param')
64
69
  return c.json({ userId: id })
@@ -66,65 +71,68 @@ app.get('/users/:id',
66
71
  )
67
72
  ```
68
73
 
69
- ## Schema Builder
74
+ ## Advanced Patterns
70
75
 
71
- `Schema` exposes TypeBox constructors:
76
+ ### Partial Updates (PATCH)
72
77
 
73
- ```typescript
74
- import { Schema } from '@gravito/mass'
78
+ Use the `partial()` utility to make all properties of a schema optional, perfect for update endpoints.
75
79
 
76
- Schema.String()
77
- Schema.Number()
78
- Schema.Boolean()
79
- Schema.Array(Schema.String())
80
+ ```typescript
81
+ import { partial } from '@gravito/mass'
80
82
 
81
- Schema.Object({
82
- name: Schema.String(),
83
- age: Schema.Number()
84
- })
83
+ const UpdateUserSchema = partial(CreateUserSchema)
85
84
 
86
- Schema.Optional(Schema.String())
87
- Schema.String({ default: 'hello' })
88
- Schema.String({ minLength: 2, maxLength: 100 })
89
- Schema.Number({ minimum: 0, maximum: 100 })
90
- Schema.String({ format: 'email' })
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
+ )
91
92
  ```
92
93
 
93
- ## Beam Client Integration
94
+ ### Custom Error Handling
94
95
 
95
- When you compose routes with `app.route()`, you get full type inference for the client:
96
+ Override the default 400 response with your own error format using the validation hook.
96
97
 
97
98
  ```typescript
98
- // app.ts
99
- import { Photon } from '@gravito/photon'
100
- import { userRoute } from './routes/user'
101
-
102
- const app = new Photon()
103
- const routes = app.route('/api/users', userRoute)
104
-
105
- export default app
106
- export type AppRoutes = typeof routes
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('Success')
109
+ )
107
110
  ```
108
111
 
109
- ```typescript
110
- // client.ts
111
- import { createBeam } from '@gravito/beam'
112
- import type { AppRoutes } from './types'
112
+ ## 🧩 API Reference
113
113
 
114
- export const createClient = (baseUrl: string) => {
115
- return createBeam<AppRoutes>(baseUrl)
116
- }
114
+ ### `validate(source, schema, hook?)`
115
+ Main middleware for schema enforcement.
116
+ - `source`: `'json' | 'query' | 'param' | 'form'`
117
+ - `schema`: A TypeBox schema instance.
118
+ - `hook`: `(result, context) => Response | undefined`
117
119
 
118
- const client = createClient('http://localhost:3000')
119
- const result = await client.api.users.login.$post({
120
- json: { username: 'user', password: 'pass' }
121
- })
122
- ```
120
+ ### `Schema`
121
+ The central builder for defining data structures. Re-exports all TypeBox builders.
122
+ - `Schema.String()`
123
+ - `Schema.Number()`
124
+ - `Schema.Boolean()`
125
+ - `Schema.Object({ ... })`
126
+ - `Schema.Array(...)`
127
+ - `Schema.Optional(...)`
128
+
129
+ ### `partial(schema)`
130
+ Recursively makes all properties in an object schema optional.
123
131
 
124
- ## Performance Notes
132
+ ## 🤝 Contributing
125
133
 
126
- TypeBox generates validators at build-time for faster runtime performance, smaller bundles, and strong TypeScript inference.
134
+ We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
127
135
 
128
- ## License
136
+ ## 📄 License
129
137
 
130
- MIT
138
+ MIT © Carl Lee
package/README.zh-TW.md CHANGED
@@ -1,14 +1,29 @@
1
- # @gravito/mass
1
+ # @gravito/mass ⚖️
2
2
 
3
- > Gravito TypeBox 驗證模組,提供高效能且完整的 TypeScript 支援。
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
- app.post('/login',
20
- validate('json', Schema.Object({
21
- username: Schema.String(),
22
- password: Schema.String()
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 { username } = c.req.valid('json')
26
- return c.json({ success: true, message: `Welcome ${username}` })
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,233 @@
1
+ import type { Context, Env, MiddlewareHandler } from '@gravito/photon';
2
+ import type { Static, 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
+ * @template S - Validation source type
168
+ * @template E - Photon environment type
169
+ * @template P - Route path type
170
+ *
171
+ * @param source - Validation source (recommend using 'query' or 'param')
172
+ * @param schema - TypeBox schema definition
173
+ * @param hook - Optional validation result hook
174
+ * @returns Photon middleware handler
175
+ *
176
+ * @example Query Parameter Coercion
177
+ * ```typescript
178
+ * const searchSchema = Type.Object({
179
+ * page: Type.Number({ minimum: 1 }),
180
+ * limit: Type.Number({ minimum: 1, maximum: 100 }),
181
+ * active: Type.Optional(Type.Boolean())
182
+ * })
183
+ *
184
+ * app.get('/search',
185
+ * validateWithCoercion('query', searchSchema),
186
+ * (c) => {
187
+ * const { page, limit, active } = c.req.valid('query')
188
+ * // All values are automatically coerced to correct types
189
+ * return c.json({ page, limit, active })
190
+ * }
191
+ * )
192
+ * ```
193
+ *
194
+ * @example Route Parameter Coercion
195
+ * ```typescript
196
+ * const paramSchema = Type.Object({
197
+ * id: Type.Number({ minimum: 1 })
198
+ * })
199
+ *
200
+ * app.get('/users/:id',
201
+ * validateWithCoercion('param', paramSchema),
202
+ * (c) => {
203
+ * const { id } = c.req.valid('param')
204
+ * // id converted from string to number
205
+ * return c.json({ userId: id })
206
+ * }
207
+ * )
208
+ * ```
209
+ *
210
+ * @example With Custom Error Handling
211
+ * ```typescript
212
+ * app.get('/items',
213
+ * validateWithCoercion('query', querySchema, (result, c) => {
214
+ * if (!result.success) {
215
+ * return c.json({
216
+ * error: 'Invalid query parameters',
217
+ * details: result.errors
218
+ * }, 400)
219
+ * }
220
+ * }),
221
+ * handler
222
+ * )
223
+ * ```
224
+ */
225
+ export declare function validateWithCoercion<T extends TSchema, S extends 'json' | 'query' | 'param' | 'form', E extends Env = Env, P extends string = string>(source: S, schema: T, hook?: (result: unknown, c: Context<E>) => Response | Promise<Response> | undefined): MiddlewareHandler<E, P, {
226
+ in: {
227
+ [K in S]: Static<T>;
228
+ };
229
+ out: {
230
+ [K in S]: Static<T>;
231
+ };
232
+ }>;
233
+ //# sourceMappingURL=coercion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coercion.d.ts","sourceRoot":"","sources":["../src/coercion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEtE,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAGrF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,OAAO,CAMT;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,QAAQ,CAKV;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,QAAQ,CAKV;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAoC/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,EAC7C,CAAC,SAAS,GAAG,GAAG,GAAG,EACnB,CAAC,SAAS,MAAM,GAAG,MAAM,EAEzB,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAClF,iBAAiB,CAClB,CAAC,EACD,CAAC,EACD;IACE,EAAE,EAAE;SAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;KAAE,CAAA;IAC3B,GAAG,EAAE;SAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;KAAE,CAAA;CAC7B,CACF,CAoDA"}