tspace-spear 1.1.9 → 1.2.1-beta.1

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.
Files changed (54) hide show
  1. package/README.md +747 -705
  2. package/{build → dist}/lib/core/decorators/context.js.map +1 -1
  3. package/{build → dist}/lib/core/decorators/controller.js +1 -1
  4. package/{build → dist}/lib/core/decorators/controller.js.map +1 -1
  5. package/{build → dist}/lib/core/decorators/headers.js.map +1 -1
  6. package/dist/lib/core/decorators/methods.js.map +1 -0
  7. package/dist/lib/core/decorators/middleware.js.map +1 -0
  8. package/{build → dist}/lib/core/decorators/statusCode.js +2 -2
  9. package/dist/lib/core/decorators/statusCode.js.map +1 -0
  10. package/dist/lib/core/decorators/swagger.js.map +1 -0
  11. package/{build → dist}/lib/core/server/index.js +298 -212
  12. package/dist/lib/core/server/index.js.map +1 -0
  13. package/{build → dist}/lib/core/server/parser-factory.js +29 -7
  14. package/dist/lib/core/server/parser-factory.js.map +1 -0
  15. package/dist/lib/core/server/radix-router.js +65 -0
  16. package/dist/lib/core/server/radix-router.js.map +1 -0
  17. package/dist/lib/core/server/router.js.map +1 -0
  18. package/{build → dist}/lib/index.js +0 -1
  19. package/{build → dist}/lib/index.js.map +1 -1
  20. package/{build → dist}/tests/benchmark.test.js +48 -9
  21. package/dist/tests/benchmark.test.js.map +1 -0
  22. package/package.json +17 -11
  23. package/build/lib/core/decorators/context.d.ts +0 -5
  24. package/build/lib/core/decorators/controller.d.ts +0 -1
  25. package/build/lib/core/decorators/headers.d.ts +0 -3
  26. package/build/lib/core/decorators/index.d.ts +0 -9
  27. package/build/lib/core/decorators/methods.d.ts +0 -5
  28. package/build/lib/core/decorators/methods.js.map +0 -1
  29. package/build/lib/core/decorators/middleware.d.ts +0 -2
  30. package/build/lib/core/decorators/middleware.js.map +0 -1
  31. package/build/lib/core/decorators/statusCode.d.ts +0 -1
  32. package/build/lib/core/decorators/statusCode.js.map +0 -1
  33. package/build/lib/core/decorators/swagger.d.ts +0 -2
  34. package/build/lib/core/decorators/swagger.js.map +0 -1
  35. package/build/lib/core/server/index.d.ts +0 -309
  36. package/build/lib/core/server/index.js.map +0 -1
  37. package/build/lib/core/server/parser-factory.d.ts +0 -24
  38. package/build/lib/core/server/parser-factory.js.map +0 -1
  39. package/build/lib/core/server/router.d.ts +0 -79
  40. package/build/lib/core/server/router.js.map +0 -1
  41. package/build/lib/core/types/index.d.ts +0 -167
  42. package/build/lib/index.d.ts +0 -11
  43. package/build/tests/benchmark.test.d.ts +0 -1
  44. package/build/tests/benchmark.test.js.map +0 -1
  45. /package/{build → dist}/lib/core/decorators/context.js +0 -0
  46. /package/{build → dist}/lib/core/decorators/headers.js +0 -0
  47. /package/{build → dist}/lib/core/decorators/index.js +0 -0
  48. /package/{build → dist}/lib/core/decorators/index.js.map +0 -0
  49. /package/{build → dist}/lib/core/decorators/methods.js +0 -0
  50. /package/{build → dist}/lib/core/decorators/middleware.js +0 -0
  51. /package/{build → dist}/lib/core/decorators/swagger.js +0 -0
  52. /package/{build → dist}/lib/core/server/router.js +0 -0
  53. /package/{build → dist}/lib/core/types/index.js +0 -0
  54. /package/{build → dist}/lib/core/types/index.js.map +0 -0
package/README.md CHANGED
@@ -1,706 +1,748 @@
1
- # tspace-spear
2
-
3
- [![NPM version](https://img.shields.io/npm/v/tspace-spear.svg)](https://www.npmjs.com)
4
- [![NPM downloads](https://img.shields.io/npm/dm/tspace-spear.svg)](https://www.npmjs.com)
5
-
6
- tspace-spear is a lightweight API framework for Node.js that is fast and highly focused on providing the best developer experience.
7
- It utilizes the native HTTP server.
8
-
9
- ## Install
10
-
11
- Install with [npm](https://www.npmjs.com/):
12
-
13
- ```sh
14
- npm install tspace-spear --save
15
-
16
- ```
17
- ## Basic Usage
18
- - [Start Server](#start-server)
19
- - [Cluster](#cluster)
20
- - [Global Prefix](#global-prefix)
21
- - [Logger](#logger)
22
- - [Format Response](#format-response)
23
- - [Notfound](#notfound)
24
- - [Response](#response)
25
- - [Catch](#catch)
26
- - [Cors](#cors)
27
- - [Body](#body)
28
- - [File Upload](#file-upload)
29
- - [Cookie](#cookie)
30
- - [Middleware](#middleware)
31
- - [Controller](#controller)
32
- - [Router](#router)
33
- - [Swagger](#swagger)
34
- - [Example CRUD](#example-crud)
35
-
36
- ## Start Server
37
- ```js
38
- import { Spear } from "tspace-spear";
39
-
40
- new Spear()
41
- .get('/' , () => 'Hello world!')
42
- .get('/json' , () => {
43
- return {
44
- message : 'Hello world!'
45
- }
46
- })
47
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
48
-
49
- ```
50
-
51
- ## Cluster
52
- ```js
53
- import { Spear } from "tspace-spear";
54
- new Spear({
55
- cluster : 3
56
- })
57
- .get('/' , () => 'Hello world!')
58
- .get('/json' , () => {
59
- return {
60
- message : 'Hello world!'
61
- }
62
- })
63
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
64
-
65
- ```
66
-
67
- ## Global Prefix
68
- ```js
69
- const app = new Spear({
70
- globalPrefix : '/api' // prefix all routes
71
- })
72
- .get('/' , () => 'Hello world!')
73
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
74
-
75
- // http://localhost:3000/api => 'Hello world!'
76
- ```
77
-
78
- ## Logger
79
- ```js
80
- const app = new Spear({
81
- logger : true
82
- })
83
- // or use this for logging
84
- .useLogger({
85
- methods : ['GET','POST'],
86
- exceptPath : /\/benchmark(\/|$)|\/favicon\.ico(\/|$)/ // or use Array ['/']
87
- })
88
- .get('/' , () => 'Hello world!')
89
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
90
-
91
- ```
92
-
93
- ## Format Response
94
-
95
- ### Notfound
96
- ```js
97
- const app = new Spear()
98
- .get('/' , () => {
99
- return {
100
- message: 'Hello world'
101
- }
102
- })
103
- .notfound(({ res } : TContext) => {
104
- return res.notFound('Not found!')
105
- })
106
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
107
- // http://localhost:3000/notfound => { success: false , message : 'Not found!' , statusCode: 404 }
108
-
109
- ```
110
-
111
- ### Response
112
- ```js
113
- const app = new Spear()
114
- .get('/' , () => {
115
- return {
116
- message: 'Hello world'
117
- }
118
- })
119
- .response((results, statusCode) => {
120
-
121
- if(typeof results === 'string') return results
122
-
123
- /// ...
124
- return {
125
- success : statusCode < 400,
126
- ...results,
127
- statusCode
128
- }
129
- })
130
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
131
- // http://localhost:3000 => { success: true , message : 'Hello World' , statusCode: 200 }
132
-
133
- ```
134
-
135
- ### Catch
136
- ```js
137
- const app = new Spear()
138
- .get('/' , () => {
139
- throw new Error('Catching failed')
140
- })
141
- .catch((err : Error , { res } : TContext) => {
142
-
143
- return res
144
- .status(500)
145
- .json({
146
- success : false,
147
- message : err?.message,
148
- statusCode : 500
149
- });
150
- })
151
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
152
- // http://localhost:3000 => { success: false , message : 'Catching failed' , statusCode: 500 }
153
-
154
- ```
155
-
156
- ## Cors
157
-
158
- ```js
159
- const app = new Spear()
160
- .cors({
161
- origins: [
162
- /^http:\/\/localhost:\d+$/
163
- ],
164
- credentials: true
165
- })
166
- //.cors() allow *
167
- .listen(port , () => console.log(`Server is now allow cors localhost:* `))
168
-
169
- ```
170
-
171
- ## Body
172
- ```js
173
-
174
- new Spear()
175
- // enable body payload
176
- .useBodyParser()
177
- .post('/' , ({ body }) => {
178
- return {
179
- yourBody : body
180
- }
181
- })
182
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
183
-
184
- ```
185
-
186
- ## File Upload
187
-
188
- ```js
189
-
190
- import { Spear } from 'tspace-spear';
191
- import path from 'path'
192
-
193
- new Spear()
194
- // use this for enable file upload
195
- .useFileUpload({
196
- limit : 1000 * 1000, // limit for file upload 1_000_000 bytes by default Infinity
197
- tempFileDir : 'temp', // folder temporary directory by default tmp
198
- removeTempFile : {
199
- remove : true, // remove temporary files by default false
200
- ms : 1000 * 60 // remove file temporary after 60 seconds
201
- }
202
- })
203
- .post('/' , ({ files } : TContext) => {
204
-
205
- // you can move the file from temporary to other folder
206
- // for example please validate the your input file
207
- const file = files.file[0]
208
- const folder = 'uploads'
209
-
210
- await file.write(path.join(path.resolve(),`${folder}/${+new Date()}.${file.extension}`))
211
-
212
- // after writed the file you should remove the temporary file
213
- await file.remove()
214
-
215
- return {
216
- files
217
- }
218
- })
219
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
220
-
221
- ```
222
-
223
- ## Cookie
224
- ```js
225
-
226
- new Spear()
227
- .useCookiesParser()
228
- .post('/' , ({ cookies }) => {
229
- return {
230
- yourCookies : cookies
231
- }
232
- })
233
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
234
- ```
235
-
236
- ## Middleware
237
- ```js
238
- // file cat-middleware.ts
239
- export default (ctx : TContext, next: TNextFunction) =>{
240
- console.log('cat middleware globals');
241
- return next();
242
- }
243
-
244
- import Spear { Router, TContext, TNextFunction } from "tspace-spear";
245
- import CatMiddleware from './cat-middleware.ts'
246
-
247
- (async () => {
248
- const port = Number(process.env.PORT ?? 3000)
249
- const app = new Spear({
250
- middlewares: [ CatMiddleware ]
251
- // if you want to import middlewares with a directory can you follow the example
252
- // middlewares : {
253
- // folder : `${__dirname}/middlewares`,
254
- // name : /middleware\.(ts|js)$/i
255
- // }
256
- })
257
-
258
- // or add a middleware
259
- app.use((ctx : TContext , next : TNextFunction) => {
260
- console.log('global middlewares')
261
- return next()
262
- })
263
-
264
- app.get('/' ((ctx,next) => {
265
- console.log('middleware on the crrent route')
266
- return next()
267
- }), ({ res } : TContext) => {
268
- return res.json({
269
- message : 'hello world!'
270
- });
271
- })
272
-
273
- app.get('/' , ({ res } : TContext) => {
274
- return res.json({
275
- message : 'hello world!'
276
- });
277
- })
278
-
279
- app.listen(port , () => console.log(`Server is now listening http://localhost:3000`))
280
-
281
- // localhost:3000
282
-
283
- })()
284
- ```
285
-
286
- ## Controller
287
- ```js
288
- import {
289
- Controller ,
290
- Middleware ,
291
- Get ,
292
- Post,
293
- Patch,
294
- Put,
295
- Delete,
296
- WriteHeader,
297
- Query,
298
- Body,
299
- Params,
300
- Cookies,
301
- Files,
302
- StatusCode,
303
- TCookies,
304
- TParams,
305
- TRequest,
306
- TResponse ,
307
- TQuery,
308
- TFiles,
309
- TContext,
310
- TNextFunction
311
- } from 'tspace-spear';
312
-
313
- import CatMiddleware from './cat-middleware.ts'
314
-
315
- // file cat-controller.ts
316
- @Controller('/cats')
317
- class CatController {
318
- @Get('/')
319
- @Middleware(CatMiddleware)
320
- @Query('test','id')
321
- @Cookies('name')
322
- public async index({ query , cookies } : {
323
- query : TQuery<{ id : string }>
324
- cookies : TCookies<{ name : string}>
325
- }) {
326
-
327
- return {
328
- query,
329
- cookies
330
- }
331
- }
332
-
333
- @Get('/:id')
334
- @Middleware(CatMiddleware)
335
- @Params('id')
336
- public async show({ params } : TContext) {
337
- return {
338
- params
339
- }
340
- }
341
-
342
- @Post('/')
343
- @Middleware(CatMiddleware)
344
- public async store({ body } : TContext) {
345
- return {
346
- body
347
- }
348
- }
349
-
350
- @Put('/:id')
351
- @Middleware(CatMiddleware)
352
- public async update({ files } : TContext) {
353
- return {
354
- files
355
- }
356
- }
357
-
358
- @Post('/upload')
359
- @Middleware(CatMiddleware)
360
- public async upload({ files } : TContext) {
361
- return {
362
- files
363
- }
364
- }
365
-
366
- @Delete('/:id')
367
- @Middleware(CatMiddleware)
368
- public async destroy({ params } : TContext) {
369
- return {
370
- params
371
- }
372
- }
373
- }
374
-
375
- import { Spear } , { Router, TContext, TNextFunction } from "tspace-spear";
376
-
377
- import CatController from './cat-controller.ts'
378
-
379
- (async () => {
380
-
381
- const app = new Spear({
382
- controllers: [ CatController ]
383
- // if you want to import controllers with a directory can you follow the example
384
- // controllers : {
385
- // folder : `${__dirname}/controllers`,
386
- // name : /controller\.(ts|js)$/i
387
- // }
388
- })
389
-
390
- app.useBodyParser()
391
- app.useCookiesParser()
392
- app.useFileUpload()
393
-
394
- app.get('/' , ( { res } : TContext) => {
395
- return res.json({
396
- message : 'hello world!'
397
- });
398
- })
399
-
400
- app.listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
401
-
402
- // localhost:3000/cats
403
- // localhost:3000/cats/41
404
-
405
- })()
406
- ```
407
-
408
- ## Router
409
-
410
- ```js
411
- import { Spear } , { Router, TContext, TNextFunction } from "tspace-spear";
412
-
413
- const app = new Spear()
414
-
415
- const router = new Router()
416
-
417
- router.groups('/my',(r) => {
418
-
419
- r.get('/cats' , ({ req , res }) => {
420
-
421
- return res.json({
422
- message : 'Hello, World!'
423
- })
424
- })
425
-
426
- return r
427
- })
428
-
429
- router.get('/cats' , ({ req , res }) => {
430
- return res.json({
431
- message : 'Hello, World!'
432
- })
433
- })
434
-
435
- app.useRouter(router)
436
-
437
- app.get('/' , ({ res } : TContext) => {
438
- return res.json({
439
- message : 'hello world!'
440
- });
441
- })
442
-
443
- let port = 3000
444
-
445
- app.listen(port , () => console.log(`Server is now listening http://localhost:3000`))
446
-
447
- // localhost:3000/my/cats
448
- // localhost:3000/cats
449
-
450
- ```
451
-
452
- ## Swagger
453
- ```js
454
-
455
- // file cat-controller.ts
456
- import {
457
- TContext,
458
- Controller,
459
- Get ,
460
- Post,
461
- Put,
462
- Patch,
463
- Delete,
464
- Swagger
465
- } from 'tspace-spear';
466
-
467
- @Controller('/cats')
468
- class CatController {
469
- @Get('/')
470
- @Swagger({
471
- query : {
472
- id : {
473
- type : 'integer'
474
- },
475
- name : {
476
- type : 'string'
477
- }
478
- }
479
- })
480
- public async index({ query } : TContext) {
481
-
482
- return {
483
- query
484
- }
485
- }
486
-
487
- @Get('/:id')
488
- @Swagger({
489
- description : '- message',
490
- query : {
491
- id : {
492
- type : 'integer'
493
- }
494
- },
495
- responses : [
496
- { status : 200 , description : "OK" , example : { id : 'catz' }},
497
- { status : 400 , description : "Bad request" , example : { id : 'catz' }}
498
- ]
499
- })
500
- public async show({ params } : TContext) {
501
- return {
502
- params
503
- }
504
- }
505
-
506
- @Post('/')
507
- @Swagger({
508
- bearerToken : true,
509
- body : {
510
- description : 'The description !',
511
- required : true,
512
- properties : {
513
- id : {
514
- type : 'integer',
515
- example : 1
516
- },
517
- name : {
518
- type : 'string',
519
- example : "xxxxx"
520
- }
521
- }
522
- }
523
- })
524
- public async store({ body } : TContext) {
525
- return {
526
- body
527
- }
528
- }
529
-
530
- @Put('/:uuid')
531
- @Swagger({
532
- bearerToken : true,
533
- body : {
534
- description : 'The description !',
535
- required : true,
536
- properties : {
537
- id : {
538
- type : 'integer',
539
- example : 1
540
- },
541
- name : {
542
- type : 'string',
543
- example : "xxxxx"
544
- }
545
- }
546
- }
547
- })
548
- public async updated({ body } : TContext) {
549
- return {
550
- body
551
- }
552
- }
553
-
554
- @Patch('/:uuid')
555
- @Swagger({
556
- bearerToken : true,
557
- body : {
558
- description : 'The description !',
559
- required : true,
560
- properties : {
561
- id : {
562
- type : 'integer',
563
- example : 1
564
- },
565
- name : {
566
- type : 'string',
567
- example : "xxxxx"
568
- }
569
- }
570
- }
571
- })
572
- public async update({ body } : TContext) {
573
- return {
574
- body
575
- }
576
- }
577
-
578
- @Delete('/:uuid')
579
- @Swagger({
580
- bearerToken : true
581
- })
582
- public async delete({ params } : TContext) {
583
- return {
584
- params
585
- }
586
- }
587
-
588
- @Post('/upload')
589
- @Swagger({
590
- bearerToken : true,
591
- files : {
592
- required : true,
593
- properties : {
594
- file : {
595
- type : 'array',
596
- items: {
597
- type:"file",
598
- format:"binary"
599
- }
600
- },
601
- name : {
602
- type : 'string'
603
- }
604
- }
605
- }
606
- })
607
- public async upload({ body , files } : TContext) {
608
- return {
609
- body,
610
- files
611
- }
612
- }
613
- }
614
-
615
- (async () => {
616
-
617
- await new Spear({
618
- controllers: [ CatController ]
619
- })
620
- .get('/' , ({ res } : TContext) => {
621
- return res.json({
622
- message : 'hello world!'
623
- });
624
- })
625
- // .useSwagger() // by default path is "/api/docs"
626
- .useSwagger({
627
- path : "/docs",
628
- servers : [
629
- { url : "http://localhost:3000" , description : "development"},
630
- { url : "http://localhost:8000" , description : "production"}
631
- ],
632
- info : {
633
- "title" : "Welcome to the the documentation",
634
- "description" : "This is the documentation"
635
- }
636
- })
637
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
638
-
639
- // localhost:3000/docs
640
- })()
641
-
642
- ```
643
-
644
- ## Example CRUD
645
- ```js
646
- import { Spear } from "tspace-spear";
647
-
648
- const spears = [
649
- {
650
- id : 1,
651
- damage : 100
652
- },
653
- {
654
- id : 2,
655
- damage : 75
656
- },
657
- {
658
- id : 3,
659
- damage : 50
660
- }
661
- ]
662
-
663
- new Spear()
664
- // enable body payload
665
- .useBodyParser()
666
- .get('/' , () => spears)
667
- .get('/:id' , ({ params }) => spears.find(spear => spear.id === Number(params.id ?? 0)))
668
- .post('/' , ({ body }) => {
669
- // please validation the your body
670
- const damage = Number(body.damage ?? (Math.random() * 100).toFixed(0))
671
-
672
- const id = spears.reduce((max, spear) => spear.id > max ? spear.id : max, 0) + 1
673
-
674
- spears.push({ id , damage })
675
-
676
- return spears.find(spear => spear.id === id)
677
- })
678
- .patch('/:id' , ({ params , body , res }) => {
679
-
680
- const damage = Number(body.damage ?? (Math.random() * 100).toFixed(0))
681
-
682
- const id = Number(params.id)
683
-
684
- const spear = spears.find(spear => spear.id === id)
685
-
686
- if (spear == null) return res.status(404).json({ message : 'Spear not found'})
687
-
688
- spear.damage = damage;
689
-
690
- return spears.find(spear => spear.id === id)
691
- })
692
- .delete('/:id', ({ params , res }) => {
693
-
694
- const id = Number(params.id)
695
-
696
- const spear = spears.find(spear => spear.id === id)
697
-
698
- if (spear == null) return res.status(404).json({ message : 'Spear not found'})
699
-
700
- spears.splice(spears.findIndex(spear => spear.id === Number(params.id ?? 0)), 1)
701
-
702
- return res.status(204).json()
703
- })
704
- .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
705
-
1
+ # tspace-spear
2
+
3
+ [![NPM version](https://img.shields.io/npm/v/tspace-spear.svg)](https://www.npmjs.com)
4
+ [![NPM downloads](https://img.shields.io/npm/dm/tspace-spear.svg)](https://www.npmjs.com)
5
+
6
+ tspace-spear is a lightweight API framework for Node.js that is fast and highly focused on providing the best developer experience.
7
+ It utilizes the native HTTP server.
8
+
9
+ ## Install
10
+
11
+ Install with [npm](https://www.npmjs.com/):
12
+
13
+ ```sh
14
+ npm install tspace-spear --save
15
+
16
+ ```
17
+ ## Basic Usage
18
+ - [Start Server](#start-server)
19
+ - [Cluster](#cluster)
20
+ - [Global Prefix](#global-prefix)
21
+ - [Logger](#logger)
22
+ - [Format Response](#format-response)
23
+ - [Notfound](#notfound)
24
+ - [Response](#response)
25
+ - [Catch](#catch)
26
+ - [Cors](#cors)
27
+ - [Body](#body)
28
+ - [File Upload](#file-upload)
29
+ - [Cookie](#cookie)
30
+ - [Middleware](#middleware)
31
+ - [Controller](#controller)
32
+ - [Router](#router)
33
+ - [Swagger](#swagger)
34
+ - [WebSocket](#web-socket)
35
+ - [Example CRUD](#example-crud)
36
+
37
+ ## Start Server
38
+ ```js
39
+ import { Spear } from "tspace-spear";
40
+
41
+ new Spear()
42
+ .get('/' , () => 'Hello world!')
43
+ .get('/json' , () => {
44
+ return {
45
+ message : 'Hello world!'
46
+ }
47
+ })
48
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
49
+
50
+ ```
51
+
52
+ ## Cluster
53
+ ```js
54
+ import { Spear } from "tspace-spear";
55
+ new Spear({
56
+ cluster : 3
57
+ })
58
+ .get('/' , () => 'Hello world!')
59
+ .get('/json' , () => {
60
+ return {
61
+ message : 'Hello world!'
62
+ }
63
+ })
64
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
65
+
66
+ ```
67
+
68
+ ## Global Prefix
69
+ ```js
70
+ const app = new Spear({
71
+ globalPrefix : '/api' // prefix all routes
72
+ })
73
+ .get('/' , () => 'Hello world!')
74
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
75
+
76
+ // http://localhost:3000/api => 'Hello world!'
77
+ ```
78
+
79
+ ## Logger
80
+ ```js
81
+ const app = new Spear({
82
+ logger : true
83
+ })
84
+ // or use this for logging
85
+ .useLogger({
86
+ methods : ['GET','POST'],
87
+ exceptPath : /\/benchmark(\/|$)|\/favicon\.ico(\/|$)/ // or use Array ['/']
88
+ })
89
+ .get('/' , () => 'Hello world!')
90
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
91
+
92
+ ```
93
+
94
+ ## Format Response
95
+
96
+ ### Notfound
97
+ ```js
98
+ const app = new Spear()
99
+ .get('/' , () => {
100
+ return {
101
+ message: 'Hello world'
102
+ }
103
+ })
104
+ .notfound(({ res } : T.Context) => {
105
+ return res.notFound('Not found!')
106
+ })
107
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
108
+ // http://localhost:3000/notfound => { success: false , message : 'Not found!' , statusCode: 404 }
109
+
110
+ ```
111
+
112
+ ### Response
113
+ ```js
114
+ const app = new Spear()
115
+ .get('/' , () => {
116
+ return {
117
+ message: 'Hello world'
118
+ }
119
+ })
120
+ .response((results, statusCode) => {
121
+
122
+ if(typeof results === 'string') return results
123
+
124
+ /// ...
125
+ return {
126
+ success : statusCode < 400,
127
+ ...results,
128
+ statusCode
129
+ }
130
+ })
131
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
132
+ // http://localhost:3000 => { success: true , message : 'Hello World' , statusCode: 200 }
133
+
134
+ ```
135
+
136
+ ### Catch
137
+ ```js
138
+ const app = new Spear()
139
+ .get('/' , () => {
140
+ throw new Error('Catching failed')
141
+ })
142
+ .catch((err : Error , { res } : T.Context) => {
143
+
144
+ return res
145
+ .status(500)
146
+ .json({
147
+ success : false,
148
+ message : err?.message,
149
+ statusCode : 500
150
+ });
151
+ })
152
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
153
+ // http://localhost:3000 => { success: false , message : 'Catching failed' , statusCode: 500 }
154
+
155
+ ```
156
+
157
+ ## Cors
158
+
159
+ ```js
160
+ const app = new Spear()
161
+ .cors({
162
+ origins: [
163
+ /^http:\/\/localhost:\d+$/
164
+ ],
165
+ credentials: true
166
+ })
167
+ //.cors() allow *
168
+ .listen(port , () => console.log(`Server is now allow cors localhost:* `))
169
+
170
+ ```
171
+
172
+ ## Body
173
+ ```js
174
+
175
+ new Spear()
176
+ // enable body payload
177
+ .useBodyParser()
178
+ .post('/' , ({ body }) => {
179
+ return {
180
+ yourBody : body
181
+ }
182
+ })
183
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
184
+
185
+ ```
186
+
187
+ ## File Upload
188
+
189
+ ```js
190
+
191
+ import { Spear, type T } from 'tspace-spear';
192
+ import path from 'path'
193
+
194
+ new Spear()
195
+ // use this for enable file upload
196
+ .useFileUpload({
197
+ limit : 1000 * 1000, // limit for file upload 1_000_000 bytes by default Infinity
198
+ tempFileDir : 'temp', // folder temporary directory by default tmp
199
+ removeTempFile : {
200
+ remove : true, // remove temporary files by default false
201
+ ms : 1000 * 60 // remove file temporary after 60 seconds
202
+ }
203
+ })
204
+ .post('/' , ({ files } : T.Context) => {
205
+
206
+ // you can move the file from temporary to other folder
207
+ // for example please validate the your input file
208
+ const file = files.file[0]
209
+ const folder = 'uploads'
210
+
211
+ await file.write(path.join(path.resolve(),`${folder}/${+new Date()}.${file.extension}`))
212
+
213
+ // after writed the file you should remove the temporary file
214
+ await file.remove()
215
+
216
+ return {
217
+ files
218
+ }
219
+ })
220
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
221
+
222
+ ```
223
+
224
+ ## Cookie
225
+ ```js
226
+
227
+ new Spear()
228
+ .useCookiesParser()
229
+ .post('/' , ({ cookies }) => {
230
+ return {
231
+ yourCookies : cookies
232
+ }
233
+ })
234
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
235
+ ```
236
+
237
+ ## Middleware
238
+ ```js
239
+ import { type T } from "tspace-spear"
240
+ // file cat-middleware.ts
241
+ export default (ctx : T.Context, next: T.NextFunction) =>{
242
+ console.log('cat middleware globals');
243
+ return next();
244
+ }
245
+
246
+ import Spear { Router, type T } from "tspace-spear";
247
+ import CatMiddleware from './cat-middleware.ts'
248
+
249
+ (async () => {
250
+ const port = Number(process.env.PORT ?? 3000)
251
+ const app = new Spear({
252
+ middlewares: [ CatMiddleware ]
253
+ // if you want to import middlewares with a directory can you follow the example
254
+ // middlewares : {
255
+ // folder : `${__dirname}/middlewares`,
256
+ // name : /middleware\.(ts|js)$/i
257
+ // }
258
+ })
259
+
260
+ // or add a middleware
261
+ app.use((ctx : T.Context , next : T.NextFunction) => {
262
+ console.log('global middlewares')
263
+ return next()
264
+ })
265
+
266
+ app.get('/' ((ctx,next) => {
267
+ console.log('middleware on the crrent route')
268
+ return next()
269
+ }), ({ res } : T.Context) => {
270
+ return res.json({
271
+ message : 'hello world!'
272
+ });
273
+ })
274
+
275
+ app.get('/' , ({ res } : T.Context) => {
276
+ return res.json({
277
+ message : 'hello world!'
278
+ });
279
+ })
280
+
281
+ app.listen(port , () => console.log(`Server is now listening http://localhost:3000`))
282
+
283
+ // localhost:3000
284
+
285
+ })()
286
+ ```
287
+
288
+ ## Controller
289
+ ```js
290
+ import {
291
+ Controller ,
292
+ Middleware ,
293
+ Get ,
294
+ Post,
295
+ Patch,
296
+ Put,
297
+ Delete,
298
+ WriteHeader,
299
+ Query,
300
+ Body,
301
+ Params,
302
+ Cookies,
303
+ Files,
304
+ StatusCode,
305
+ type T
306
+ } from 'tspace-spear';
307
+
308
+ import CatMiddleware from './cat-middleware.ts'
309
+
310
+ // file cat-controller.ts
311
+ @Controller('/cats')
312
+ class CatController {
313
+ @Get('/')
314
+ @Middleware(CatMiddleware)
315
+ @Query('test','id')
316
+ @Cookies('name')
317
+ public async index({ query , cookies } : {
318
+ query : T.Query<{ id : string }>
319
+ cookies : T.Cookies<{ name : string}>
320
+ }) {
321
+
322
+ return {
323
+ query,
324
+ cookies
325
+ }
326
+ }
327
+
328
+ @Get('/:id')
329
+ @Middleware(CatMiddleware)
330
+ @Params('id')
331
+ public async show({ params } : T.Context) {
332
+ return {
333
+ params
334
+ }
335
+ }
336
+
337
+ @Post('/')
338
+ @Middleware(CatMiddleware)
339
+ public async store({ body } : T.Context) {
340
+ return {
341
+ body
342
+ }
343
+ }
344
+
345
+ @Put('/:id')
346
+ @Middleware(CatMiddleware)
347
+ public async update({ files } : T.Context) {
348
+ return {
349
+ files
350
+ }
351
+ }
352
+
353
+ @Post('/upload')
354
+ @Middleware(CatMiddleware)
355
+ public async upload({ files } : T.Context) {
356
+ return {
357
+ files
358
+ }
359
+ }
360
+
361
+ @Delete('/:id')
362
+ @Middleware(CatMiddleware)
363
+ public async destroy({ params } : T.Context) {
364
+ return {
365
+ params
366
+ }
367
+ }
368
+ }
369
+
370
+ import { Spear } , { Router, type T } from "tspace-spear";
371
+
372
+ import CatController from './cat-controller.ts'
373
+
374
+ (async () => {
375
+
376
+ const app = new Spear({
377
+ controllers: [ CatController ]
378
+ // if you want to import controllers with a directory can you follow the example
379
+ // controllers : {
380
+ // folder : `${__dirname}/controllers`,
381
+ // name : /controller\.(ts|js)$/i
382
+ // }
383
+ })
384
+
385
+ app.useBodyParser()
386
+ app.useCookiesParser()
387
+ app.useFileUpload()
388
+
389
+ app.get('/' , ( { res } : T.Context) => {
390
+ return res.json({
391
+ message : 'hello world!'
392
+ });
393
+ })
394
+
395
+ app.listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
396
+
397
+ // localhost:3000/cats
398
+ // localhost:3000/cats/41
399
+
400
+ })()
401
+ ```
402
+
403
+ ## Router
404
+
405
+ ```js
406
+ import { Spear, Router, type T } from "tspace-spear";
407
+
408
+ const app = new Spear()
409
+
410
+ const router = new Router()
411
+
412
+ router.groups('/my',(r) => {
413
+
414
+ r.get('/cats' , ({ req , res }) => {
415
+
416
+ return res.json({
417
+ message : 'Hello, World!'
418
+ })
419
+ })
420
+
421
+ return r
422
+ })
423
+
424
+ router.get('/cats' , ({ req , res }) => {
425
+ return res.json({
426
+ message : 'Hello, World!'
427
+ })
428
+ })
429
+
430
+ app.useRouter(router)
431
+
432
+ app.get('/' , ({ res } : T.Context) => {
433
+ return res.json({
434
+ message : 'hello world!'
435
+ });
436
+ })
437
+
438
+ let port = 3000
439
+
440
+ app.listen(port , () => console.log(`Server is now listening http://localhost:3000`))
441
+
442
+ // localhost:3000/my/cats
443
+ // localhost:3000/cats
444
+
445
+ ```
446
+
447
+ ## Swagger
448
+ ```js
449
+
450
+ // file cat-controller.ts
451
+ import {
452
+ type T,
453
+ Controller,
454
+ Get ,
455
+ Post,
456
+ Put,
457
+ Patch,
458
+ Delete,
459
+ Swagger
460
+ } from 'tspace-spear';
461
+
462
+ @Controller('/cats')
463
+ class CatController {
464
+ @Get('/')
465
+ @Swagger({
466
+ query : {
467
+ id : {
468
+ type : 'integer'
469
+ },
470
+ name : {
471
+ type : 'string'
472
+ }
473
+ }
474
+ })
475
+ public async index({ query } : T.Context) {
476
+
477
+ return {
478
+ query
479
+ }
480
+ }
481
+
482
+ @Get('/:id')
483
+ @Swagger({
484
+ description : '- message',
485
+ query : {
486
+ id : {
487
+ type : 'integer'
488
+ }
489
+ },
490
+ responses : [
491
+ { status : 200 , description : "OK" , example : { id : 'catz' }},
492
+ { status : 400 , description : "Bad request" , example : { id : 'catz' }}
493
+ ]
494
+ })
495
+ public async show({ params } : T.Context) {
496
+ return {
497
+ params
498
+ }
499
+ }
500
+
501
+ @Post('/')
502
+ @Swagger({
503
+ bearerToken : true,
504
+ body : {
505
+ description : 'The description !',
506
+ required : true,
507
+ properties : {
508
+ id : {
509
+ type : 'integer',
510
+ example : 1
511
+ },
512
+ name : {
513
+ type : 'string',
514
+ example : "xxxxx"
515
+ }
516
+ }
517
+ }
518
+ })
519
+ public async store({ body } : T.Context) {
520
+ return {
521
+ body
522
+ }
523
+ }
524
+
525
+ @Put('/:uuid')
526
+ @Swagger({
527
+ bearerToken : true,
528
+ body : {
529
+ description : 'The description !',
530
+ required : true,
531
+ properties : {
532
+ id : {
533
+ type : 'integer',
534
+ example : 1
535
+ },
536
+ name : {
537
+ type : 'string',
538
+ example : "xxxxx"
539
+ }
540
+ }
541
+ }
542
+ })
543
+ public async updated({ body } : T.Context) {
544
+ return {
545
+ body
546
+ }
547
+ }
548
+
549
+ @Patch('/:uuid')
550
+ @Swagger({
551
+ bearerToken : true,
552
+ body : {
553
+ description : 'The description !',
554
+ required : true,
555
+ properties : {
556
+ id : {
557
+ type : 'integer',
558
+ example : 1
559
+ },
560
+ name : {
561
+ type : 'string',
562
+ example : "xxxxx"
563
+ }
564
+ }
565
+ }
566
+ })
567
+ public async update({ body } : T.Context) {
568
+ return {
569
+ body
570
+ }
571
+ }
572
+
573
+ @Delete('/:uuid')
574
+ @Swagger({
575
+ bearerToken : true
576
+ })
577
+ public async delete({ params } : T.Context) {
578
+ return {
579
+ params
580
+ }
581
+ }
582
+
583
+ @Post('/upload')
584
+ @Swagger({
585
+ bearerToken : true,
586
+ files : {
587
+ required : true,
588
+ properties : {
589
+ file : {
590
+ type : 'array',
591
+ items: {
592
+ type:"file",
593
+ format:"binary"
594
+ }
595
+ },
596
+ name : {
597
+ type : 'string'
598
+ }
599
+ }
600
+ }
601
+ })
602
+ public async upload({ body , files } : T.Context) {
603
+ return {
604
+ body,
605
+ files
606
+ }
607
+ }
608
+ }
609
+
610
+ (async () => {
611
+
612
+ await new Spear({
613
+ controllers: [ CatController ]
614
+ })
615
+ .get('/' , ({ res } : T.Context) => {
616
+ return res.json({
617
+ message : 'hello world!'
618
+ });
619
+ })
620
+ // .useSwagger() // by default path is "/api/docs"
621
+ .useSwagger({
622
+ path : "/docs",
623
+ servers : [
624
+ { url : "http://localhost:3000" , description : "development"},
625
+ { url : "http://localhost:8000" , description : "production"}
626
+ ],
627
+ info : {
628
+ "title" : "Welcome to the the documentation",
629
+ "description" : "This is the documentation"
630
+ }
631
+ })
632
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
633
+
634
+ // localhost:3000/docs
635
+ })()
636
+
637
+ ```
638
+
639
+ ## WebSocket
640
+ ```js
641
+ import { Spear } from "tspace-spear";
642
+
643
+ new Spear()
644
+ .get('/', () => 'Hello wor1ld!')
645
+ .post('/', ({ req , res , headers , query })=> {
646
+ return res.tooManyRequests()
647
+ })
648
+ .ws(() => {
649
+ return {
650
+ connection: (ws) => {
651
+ ws.send(JSON.stringify({ type: 'welcome', message: 'Welcome to the server!' }));
652
+ },
653
+ message: (ws, msg) => {
654
+ const data = JSON.parse(msg.toString());
655
+
656
+ switch (data.type) {
657
+ case 'chat':
658
+ console.log('Chat message:', data.text);
659
+ ws.send(JSON.stringify({ type: 'chat_ack', message: 'Chat received!' }));
660
+ break;
661
+
662
+ case 'ping':
663
+ console.log('Ping received');
664
+ ws.send(JSON.stringify({ type: 'pong' }));
665
+ break;
666
+
667
+ default:
668
+ ws.send(JSON.stringify({ type: 'error', message: 'Unknown message type' }));
669
+ }
670
+ },
671
+ close: (ws, code, reason) => {
672
+ console.log('Client disconnected');
673
+ },
674
+ error: (ws, error) => {
675
+ console.error('WebSocket error:', error);
676
+ }
677
+ }
678
+ })
679
+ .listen(3000 , ({ port , server }) => {
680
+ console.log(`server listening on : http://localhost:${port}`)
681
+ })
682
+
683
+
684
+ ```
685
+
686
+ ## Example CRUD
687
+ ```js
688
+ import { Spear } from "tspace-spear";
689
+
690
+ const spears = [
691
+ {
692
+ id : 1,
693
+ damage : 100
694
+ },
695
+ {
696
+ id : 2,
697
+ damage : 75
698
+ },
699
+ {
700
+ id : 3,
701
+ damage : 50
702
+ }
703
+ ]
704
+
705
+ new Spear()
706
+ // enable body payload
707
+ .useBodyParser()
708
+ .get('/' , () => spears)
709
+ .get('/:id' , ({ params }) => spears.find(spear => spear.id === Number(params.id ?? 0)))
710
+ .post('/' , ({ body }) => {
711
+ // please validation the your body
712
+ const damage = Number(body.damage ?? (Math.random() * 100).toFixed(0))
713
+
714
+ const id = spears.reduce((max, spear) => spear.id > max ? spear.id : max, 0) + 1
715
+
716
+ spears.push({ id , damage })
717
+
718
+ return spears.find(spear => spear.id === id)
719
+ })
720
+ .patch('/:id' , ({ params , body , res }) => {
721
+
722
+ const damage = Number(body.damage ?? (Math.random() * 100).toFixed(0))
723
+
724
+ const id = Number(params.id)
725
+
726
+ const spear = spears.find(spear => spear.id === id)
727
+
728
+ if (spear == null) return res.status(404).json({ message : 'Spear not found'})
729
+
730
+ spear.damage = damage;
731
+
732
+ return spears.find(spear => spear.id === id)
733
+ })
734
+ .delete('/:id', ({ params , res }) => {
735
+
736
+ const id = Number(params.id)
737
+
738
+ const spear = spears.find(spear => spear.id === id)
739
+
740
+ if (spear == null) return res.status(404).json({ message : 'Spear not found'})
741
+
742
+ spears.splice(spears.findIndex(spear => spear.id === Number(params.id ?? 0)), 1)
743
+
744
+ return res.status(204).json()
745
+ })
746
+ .listen(3000 , () => console.log(`Server is now listening http://localhost:3000`))
747
+
706
748
  ```