@athenna/http 1.8.0 → 1.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@athenna/http",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "The Athenna Http server. Built on top of fastify.",
5
5
  "license": "MIT",
6
6
  "author": "João Lenon <lenon@athenna.io>",
@@ -7,8 +7,8 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
- import { Is } from '@athenna/common'
11
10
  import { Config } from '@athenna/config'
11
+ import { Is, Json } from '@athenna/common'
12
12
 
13
13
  export class Request {
14
14
  /**
@@ -149,15 +149,66 @@ export class Request {
149
149
  return this.headers[header] || defaultValue
150
150
  }
151
151
 
152
+ /**
153
+ * Get only the selected values from the request body.
154
+ *
155
+ * @param {string} keys
156
+ * @return {any}
157
+ */
158
+ only(...keys) {
159
+ const body = {}
160
+
161
+ Object.keys(this.body).forEach(key => {
162
+ if (!keys.includes(key)) {
163
+ return
164
+ }
165
+
166
+ body[key] = this.body[key]
167
+ })
168
+
169
+ return body
170
+ }
171
+
172
+ /**
173
+ * Get all the values from the request body except the selected ones.
174
+ *
175
+ * @param {string[]} keys
176
+ * @return {any}
177
+ */
178
+ except(...keys) {
179
+ const body = {}
180
+
181
+ Object.keys(this.body).forEach(key => {
182
+ if (keys.includes(key)) {
183
+ return
184
+ }
185
+
186
+ body[key] = this.body[key]
187
+ })
188
+
189
+ return body
190
+ }
191
+
192
+ /**
193
+ * Get a value from the request body or the default value.
194
+ *
195
+ * @param {string} key
196
+ * @param {string} [defaultValue]
197
+ * @return {any}
198
+ */
199
+ input(key, defaultValue) {
200
+ return this.payload(key, defaultValue)
201
+ }
202
+
152
203
  /**
153
204
  * Get a value from the request body or the default value.
154
205
  *
155
- * @param {string} payload
206
+ * @param {string} key
156
207
  * @param {string} [defaultValue]
157
208
  * @return {any}
158
209
  */
159
- payload(payload, defaultValue) {
160
- return this.body[payload] || defaultValue
210
+ payload(key, defaultValue) {
211
+ return Json.get(this.body, key, defaultValue)
161
212
  }
162
213
 
163
214
  /**
@@ -119,6 +119,8 @@ export class Response {
119
119
  redirectTo(url, statusCode) {
120
120
  if (statusCode) {
121
121
  this.#response.redirect(statusCode, url)
122
+
123
+ return
122
124
  }
123
125
 
124
126
  this.#response.redirect(url)
@@ -76,6 +76,13 @@ export class Route {
76
76
  */
77
77
  #swaggerOptions
78
78
 
79
+ /**
80
+ * Rate limit options of this route.
81
+ *
82
+ * @type {any}
83
+ */
84
+ #rateLimitOptions
85
+
79
86
  /**
80
87
  * Creates a new instance of Route.
81
88
  *
@@ -95,6 +102,7 @@ export class Route {
95
102
 
96
103
  this.#helmetOptions = {}
97
104
  this.#swaggerOptions = {}
105
+ this.#rateLimitOptions = {}
98
106
 
99
107
  RouteHelper.getParamsName(url).forEach(param => this.param(param))
100
108
 
@@ -221,6 +229,25 @@ export class Route {
221
229
  return this
222
230
  }
223
231
 
232
+ /**
233
+ * Set up all rate limit options for route.
234
+ *
235
+ * @param {any} options
236
+ * @param {boolean} [override]
237
+ * @return {Route}
238
+ */
239
+ rateLimit(options, override = true) {
240
+ if (!override) {
241
+ this.#rateLimitOptions = Options.create(this.#rateLimitOptions, options)
242
+
243
+ return this
244
+ }
245
+
246
+ this.#rateLimitOptions = options
247
+
248
+ return this
249
+ }
250
+
224
251
  /**
225
252
  * Set a summary for the route swagger docs.
226
253
  *
@@ -351,6 +378,7 @@ export class Route {
351
378
  middlewares: this.#routeMiddlewares,
352
379
  helmetOptions: this.#helmetOptions,
353
380
  swaggerOptions: this.#swaggerOptions,
381
+ rateLimitOptions: this.#rateLimitOptions,
354
382
  }
355
383
 
356
384
  if (Is.String(this.#handler)) {
@@ -82,6 +82,20 @@ export class RouteGroup {
82
82
  return this
83
83
  }
84
84
 
85
+ /**
86
+ * Set up rate limit options for route group.
87
+ *
88
+ * @param {any} options
89
+ * @return {RouteGroup}
90
+ */
91
+ rateLimit(options) {
92
+ this.routes.forEach(route => {
93
+ this.#invoke(route, 'rateLimit', [options, false])
94
+ })
95
+
96
+ return this
97
+ }
98
+
85
99
  /**
86
100
  * Invoke a method from route.
87
101
  *
@@ -106,7 +106,7 @@ export class RouteResource {
106
106
  */
107
107
  helmet(action, options) {
108
108
  if (!options) {
109
- this.routes.forEach(route => route.helmet(options))
109
+ this.routes.forEach(route => route.helmet(action))
110
110
 
111
111
  return this
112
112
  }
@@ -133,7 +133,7 @@ export class RouteResource {
133
133
  */
134
134
  swagger(action, options) {
135
135
  if (!options) {
136
- this.routes.forEach(route => route.swagger(options))
136
+ this.routes.forEach(route => route.swagger(action))
137
137
 
138
138
  return this
139
139
  }
@@ -151,6 +151,33 @@ export class RouteResource {
151
151
  return this
152
152
  }
153
153
 
154
+ /**
155
+ * Set up rate limit options for route resource method.
156
+ *
157
+ * @param {string|any} action
158
+ * @param {any} [options]
159
+ * @return {RouteResource}
160
+ */
161
+ rateLimit(action, options) {
162
+ if (!options) {
163
+ this.routes.forEach(route => route.rateLimit(action))
164
+
165
+ return this
166
+ }
167
+
168
+ const resourceName = `${this.#resourceName}.${action}`
169
+
170
+ this.routes.forEach(route => {
171
+ if (route.name !== resourceName) {
172
+ return
173
+ }
174
+
175
+ route.rateLimit(options)
176
+ })
177
+
178
+ return this
179
+ }
180
+
154
181
  /**
155
182
  * Create the route.
156
183
  *
@@ -270,6 +270,7 @@ export class Router {
270
270
  {
271
271
  helmet: route.helmetOptions,
272
272
  schema: route.swaggerOptions,
273
+ config: { rateLimit: route.rateLimitOptions },
273
274
  },
274
275
  )
275
276
  })
package/src/index.d.ts CHANGED
@@ -8,10 +8,11 @@
8
8
  */
9
9
 
10
10
  import { Facade } from '@athenna/ioc'
11
- import { Exception } from '@athenna/common'
11
+ import { Exception, Json } from '@athenna/common'
12
12
  import { OpenAPIV2, OpenAPIV3 } from 'openapi-types'
13
13
  import { FastifyHelmetOptions } from '@fastify/helmet'
14
14
  import { FastifyReply, FastifyRequest, RouteOptions } from 'fastify'
15
+ import { RateLimitOptions } from '@fastify/rate-limit'
15
16
 
16
17
  export const Server: Facade & Http
17
18
  export const Route: Facade & Router.Router
@@ -390,6 +391,14 @@ declare module Router {
390
391
  */
391
392
  swagger(options: FastifySwaggerSchema): this
392
393
 
394
+ /**
395
+ * Set up all rate limit options for route.
396
+ *
397
+ * @param {any} options
398
+ * @return {Route}
399
+ */
400
+ rateLimit(options: RateLimitOptions): this
401
+
393
402
  /**
394
403
  * Set a summary for the route swagger docs.
395
404
  *
@@ -550,6 +559,23 @@ declare module Router {
550
559
  * @return {RouteResource}
551
560
  */
552
561
  swagger(action: string, options: FastifySwaggerSchema): this
562
+
563
+ /**
564
+ * Set up rate limit options for route resource method.
565
+ *
566
+ * @param {RateLimitOptions} options
567
+ * @return {RouteResource}
568
+ */
569
+ rateLimit(options: RateLimitOptions): this
570
+
571
+ /**
572
+ * Set up rate limit options for route resource method.
573
+ *
574
+ * @param {string} action
575
+ * @param {RateLimitOptions} options
576
+ * @return {RouteResource}
577
+ */
578
+ rateLimit(action: string, options: RateLimitOptions): this
553
579
  }
554
580
 
555
581
  export class RouteGroup {
@@ -604,6 +630,14 @@ declare module Router {
604
630
  * @return {RouteGroup}
605
631
  */
606
632
  swagger(options: FastifySwaggerSchema): this
633
+
634
+ /**
635
+ * Set up rate limit options for route group.
636
+ *
637
+ * @param {any} options
638
+ * @return {RouteGroup}
639
+ */
640
+ rateLimit(options: RateLimitOptions): this
607
641
  }
608
642
 
609
643
  export class Router {
@@ -850,14 +884,42 @@ export interface RequestContract {
850
884
  */
851
885
  header(header, defaultValue): any
852
886
 
887
+ /**
888
+ * Get only the selected values from the request body.
889
+ *
890
+ * @param {string} keys
891
+ * @return {any}
892
+ */
893
+ only(...keys: string[]): any
894
+ only(keys: string[]): any
895
+
896
+ /**
897
+ * Get all the values from the request body except the selected ones.
898
+ *
899
+ * @param {string[]} keys
900
+ * @return {any}
901
+ */
902
+ except(...keys: string[]): any
903
+ except(keys: string): any
904
+
853
905
  /**
854
906
  * Get a value from the request body or the default value.
855
907
  *
856
- * @param {string} payload
857
- * @param {string} [defaultValue]
908
+ * @param {string} key
909
+ * @param {any} [defaultValue]
910
+ * @return {any}
911
+ */
912
+ input(key: string, defaultValue?: any): any
913
+
914
+ /**
915
+ * Get a value from the request body or the default value.
916
+ *
917
+ * @param {string} key
918
+ * @param {any} [defaultValue]
858
919
  * @return {any}
859
920
  */
860
- payload(payload, defaultValue): any
921
+ payload(key: string, defaultValue?: any): any
922
+
861
923
  /**
862
924
  * Get the default fastify request object.
863
925
  *
@@ -928,19 +990,10 @@ export interface ResponseContract {
928
990
  /**
929
991
  * Redirect the response to other url with different status code.
930
992
  *
931
- * @param {string} url
932
993
  * @return {void}
933
994
  */
934
995
  redirectTo(url: string): Promise<void> | void
935
-
936
- /**
937
- * Redirect the response to other url with different status code.
938
- *
939
- * @param {string} url
940
- * @param {number} statusCode
941
- * @return {void}
942
- */
943
- redirectTo(url: string, statusCode: number): Promise<void>
996
+ redirectTo(url: string, statusCode: number): Promise<void> | void
944
997
 
945
998
  /**
946
999
  * Get the default fastify response object.