@ahoo-wang/fetcher-decorator 0.6.0 → 0.6.5

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
@@ -6,6 +6,7 @@
6
6
  [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher-decorator.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher-decorator.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-decorator)
8
8
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40ahoo-wang%2Ffetcher-decorator)](https://www.npmjs.com/package/@ahoo-wang/fetcher-decorator)
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/fetcher)
9
10
 
10
11
  Decorator support for Fetcher HTTP client. Enables clean, declarative API service definitions using TypeScript
11
12
  decorators.
@@ -62,10 +63,7 @@ class UserService {
62
63
  }
63
64
 
64
65
  @get('/{id}')
65
- getUser(
66
- @path('id') id: number,
67
- @query('include') include: string,
68
- ): Promise<Response> {
66
+ getUser(@path() id: number, @query() include: string): Promise<Response> {
69
67
  throw new Error('Implementation will be generated automatically.');
70
68
  }
71
69
  }
@@ -147,7 +145,7 @@ Defines an OPTIONS endpoint.
147
145
  ```typescript
148
146
  class UserService {
149
147
  @get('/{id}', { timeout: 3000 })
150
- getUser(@path('id') id: number): Promise<Response> {
148
+ getUser(@path() id: number): Promise<Response> {
151
149
  throw new Error('Implementation will be generated automatically.');
152
150
  }
153
151
 
@@ -162,31 +160,40 @@ class UserService {
162
160
 
163
161
  #### `@path(name)`
164
162
 
165
- Defines a path parameter.
163
+ Defines a path parameter. The name is optional - if not provided, it will be automatically extracted from the method
164
+ parameter name.
166
165
 
167
166
  **Parameters:**
168
167
 
169
- - `name`: Name of the parameter (used in the path template)
168
+ - `name`: Name of the parameter (used in the path template, optional - auto-extracted if not provided)
170
169
 
171
170
  #### `@query(name)`
172
171
 
173
- Defines a query parameter.
172
+ Defines a query parameter. The name is optional - if not provided, it will be automatically extracted from the method
173
+ parameter name.
174
174
 
175
175
  **Parameters:**
176
176
 
177
- - `name`: Name of the parameter (used in the query string)
177
+ - `name`: Name of the parameter (used in the query string, optional - auto-extracted if not provided)
178
178
 
179
179
  #### `@body()`
180
180
 
181
- Defines a request body.
181
+ Defines a request body. Body parameters don't have names since there's only one body per request.
182
182
 
183
183
  #### `@header(name)`
184
184
 
185
- Defines a header parameter.
185
+ Defines a header parameter. The name is optional - if not provided, it will be automatically extracted from the method
186
+ parameter name.
186
187
 
187
188
  **Parameters:**
188
189
 
189
- - `name`: Name of the header
190
+ - `name`: Name of the header (optional - auto-extracted if not provided)
191
+
192
+ #### `@request()`
193
+
194
+ Defines a request parameter that will be used as the base request object. This allows you to pass a complete
195
+ FetcherRequest
196
+ object to customize the request configuration.
190
197
 
191
198
  **Example:**
192
199
 
@@ -195,14 +202,19 @@ class UserService {
195
202
  @get('/search')
196
203
  searchUsers(
197
204
  @query('q') query: string,
198
- @query('limit') limit: number,
205
+ @query() limit: number,
199
206
  @header('Authorization') auth: string,
200
207
  ): Promise<Response> {
201
208
  throw new Error('Implementation will be generated automatically.');
202
209
  }
203
210
 
211
+ @post('/users')
212
+ createUsers(@request() request: FetcherRequest): Promise<Response> {
213
+ throw new Error('Implementation will be generated automatically.');
214
+ }
215
+
204
216
  @put('/{id}')
205
- updateUser(@path('id') id: number, @body() user: User): Promise<Response> {
217
+ updateUser(@path() id: number, @body() user: User): Promise<Response> {
206
218
  throw new Error('Implementation will be generated automatically.');
207
219
  }
208
220
  }
@@ -224,7 +236,7 @@ class BaseService {
224
236
  @api('/users')
225
237
  class UserService extends BaseService {
226
238
  @get('/{id}')
227
- getUser(@path('id') id: number): Promise<Response> {
239
+ getUser(@path() id: number): Promise<Response> {
228
240
  throw new Error('Implementation will be generated automatically.');
229
241
  }
230
242
  }
@@ -239,8 +251,35 @@ class ComplexService {
239
251
  batchOperation(
240
252
  @body() items: Item[],
241
253
  @header('X-Request-ID') requestId: string,
242
- @query('dryRun') dryRun: boolean = false,
254
+ @query() dryRun: boolean = false,
255
+ ): Promise<Response> {
256
+ throw new Error('Implementation will be generated automatically.');
257
+ }
258
+ }
259
+ ```
260
+
261
+ ### Request Merging
262
+
263
+ When using the `@request()` decorator, the provided `FetcherRequest` object is merged with endpoint-specific
264
+ configuration using a sophisticated merging strategy:
265
+
266
+ - **Nested objects** (path, query, headers) are recursively merged, with parameter values taking precedence
267
+ - **Primitive values** (method, body, timeout, signal) from the parameter request override endpoint values
268
+ - **Empty objects** are handled gracefully, falling back to endpoint configuration
269
+
270
+ ```typescript
271
+
272
+ @api('/users')
273
+ class UserService {
274
+ @post('/')
275
+ createUsers(
276
+ @body() user: User,
277
+ @request() request: FetcherRequest,
243
278
  ): Promise<Response> {
279
+ // The final request will merge:
280
+ // - Endpoint method (POST)
281
+ // - Body parameter (user object)
282
+ // - Any configuration from the request parameter
244
283
  throw new Error('Implementation will be generated automatically.');
245
284
  }
246
285
  }
package/README.zh-CN.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher-decorator.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher-decorator.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-decorator)
8
8
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40ahoo-wang%2Ffetcher-decorator)](https://www.npmjs.com/package/@ahoo-wang/fetcher-decorator)
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/fetcher)
9
10
 
10
11
  Fetcher HTTP 客户端的装饰器支持。使用 TypeScript 装饰器实现简洁、声明式的 API 服务定义。
11
12
 
@@ -61,10 +62,7 @@ class UserService {
61
62
  }
62
63
 
63
64
  @get('/{id}')
64
- getUser(
65
- @path('id') id: number,
66
- @query('include') include: string,
67
- ): Promise<Response> {
65
+ getUser(@path() id: number, @query() include: string): Promise<Response> {
68
66
  throw new Error('实现将自动生成');
69
67
  }
70
68
  }
@@ -146,7 +144,7 @@ class ApiService {
146
144
  ```typescript
147
145
  class UserService {
148
146
  @get('/{id}', { timeout: 3000 })
149
- getUser(@path('id') id: number): Promise<Response> {
147
+ getUser(@path() id: number): Promise<Response> {
150
148
  throw new Error('实现将自动生成');
151
149
  }
152
150
 
@@ -161,31 +159,35 @@ class UserService {
161
159
 
162
160
  #### `@path(name)`
163
161
 
164
- 定义路径参数。
162
+ 定义路径参数。名称是可选的 - 如果未提供,将使用反射从方法参数名自动提取。
165
163
 
166
164
  **参数:**
167
165
 
168
- - `name`: 参数名称(在路径模板中使用)
166
+ - `name`: 参数名称(在路径模板中使用,可选 - 如果未提供则自动提取)
169
167
 
170
168
  #### `@query(name)`
171
169
 
172
- 定义查询参数。
170
+ 定义查询参数。名称是可选的 - 如果未提供,将使用反射从方法参数名自动提取。
173
171
 
174
172
  **参数:**
175
173
 
176
- - `name`: 参数名称(在查询字符串中使用)
174
+ - `name`: 参数名称(在查询字符串中使用,可选 - 如果未提供则自动提取)
177
175
 
178
176
  #### `@body()`
179
177
 
180
- 定义请求体。
178
+ 定义请求体。请求体参数没有名称,因为每个请求只有一个请求体。
181
179
 
182
180
  #### `@header(name)`
183
181
 
184
- 定义头部参数。
182
+ 定义头部参数。名称是可选的 - 如果未提供,将使用反射从方法参数名自动提取。
185
183
 
186
184
  **参数:**
187
185
 
188
- - `name`: 头部名称
186
+ - `name`: 头部名称(可选 - 如果未提供则自动提取)
187
+
188
+ #### `@request()`
189
+
190
+ 定义请求参数,将用作基础请求对象。这允许您传递一个完整的 FetcherRequest 对象来自定义请求配置。
189
191
 
190
192
  **示例:**
191
193
 
@@ -194,12 +196,17 @@ class UserService {
194
196
  @get('/search')
195
197
  searchUsers(
196
198
  @query('q') query: string,
197
- @query('limit') limit: number,
199
+ @query() limit: number,
198
200
  @header('Authorization') auth: string,
199
201
  ): Promise<Response> {
200
202
  throw new Error('实现将自动生成');
201
203
  }
202
204
 
205
+ @post('/users')
206
+ createUsers(@request() request: FetcherRequest): Promise<Response> {
207
+ throw new Error('实现将自动生成');
208
+ }
209
+
203
210
  @put('/{id}')
204
211
  updateUser(@path('id') id: number, @body() user: User): Promise<Response> {
205
212
  throw new Error('实现将自动生成');
@@ -223,7 +230,7 @@ class BaseService {
223
230
  @api('/users')
224
231
  class UserService extends BaseService {
225
232
  @get('/{id}')
226
- getUser(@path('id') id: number): Promise<Response> {
233
+ getUser(@path() id: number): Promise<Response> {
227
234
  throw new Error('实现将自动生成');
228
235
  }
229
236
  }
@@ -238,8 +245,34 @@ class ComplexService {
238
245
  batchOperation(
239
246
  @body() items: Item[],
240
247
  @header('X-Request-ID') requestId: string,
241
- @query('dryRun') dryRun: boolean = false,
248
+ @query() dryRun: boolean = false,
249
+ ): Promise<Response> {
250
+ throw new Error('实现将自动生成');
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### 请求合并
256
+
257
+ 当使用 `@request()` 装饰器时,提供的 `FetcherRequest` 对象会使用复杂的合并策略与端点特定配置进行合并:
258
+
259
+ - **嵌套对象**(路径、查询、头部)会被递归合并,参数值优先
260
+ - **基本值**(方法、请求体、超时、信号)来自参数请求的值会覆盖端点值
261
+ - **空对象**会被优雅地处理,回退到端点配置
262
+
263
+ ```typescript
264
+
265
+ @api('/users')
266
+ class UserService {
267
+ @post('/')
268
+ createUsers(
269
+ @body() user: User,
270
+ @request() request: FetcherRequest,
242
271
  ): Promise<Response> {
272
+ // 最终请求将合并:
273
+ // - 端点方法(POST)
274
+ // - 请求体参数(user 对象)
275
+ // - 来自 request 参数的任何配置
243
276
  throw new Error('实现将自动生成');
244
277
  }
245
278
  }