@owlmeans/server-api 0.1.0

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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +613 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/consts.d.ts +5 -0
  5. package/build/consts.d.ts.map +1 -0
  6. package/build/consts.js +5 -0
  7. package/build/consts.js.map +1 -0
  8. package/build/errors.d.ts +14 -0
  9. package/build/errors.d.ts.map +1 -0
  10. package/build/errors.js +27 -0
  11. package/build/errors.js.map +1 -0
  12. package/build/helper.d.ts +13 -0
  13. package/build/helper.d.ts.map +1 -0
  14. package/build/helper.js +53 -0
  15. package/build/helper.js.map +1 -0
  16. package/build/index.d.ts +6 -0
  17. package/build/index.d.ts.map +1 -0
  18. package/build/index.js +5 -0
  19. package/build/index.js.map +1 -0
  20. package/build/server.d.ts +7 -0
  21. package/build/server.d.ts.map +1 -0
  22. package/build/server.js +146 -0
  23. package/build/server.js.map +1 -0
  24. package/build/types.d.ts +21 -0
  25. package/build/types.d.ts.map +1 -0
  26. package/build/types.js +2 -0
  27. package/build/types.js.map +1 -0
  28. package/build/utils/context.d.ts +4 -0
  29. package/build/utils/context.d.ts.map +1 -0
  30. package/build/utils/context.js +5 -0
  31. package/build/utils/context.js.map +1 -0
  32. package/build/utils/error.d.ts +3 -0
  33. package/build/utils/error.d.ts.map +1 -0
  34. package/build/utils/error.js +16 -0
  35. package/build/utils/error.js.map +1 -0
  36. package/build/utils/guards.d.ts +9 -0
  37. package/build/utils/guards.d.ts.map +1 -0
  38. package/build/utils/guards.js +57 -0
  39. package/build/utils/guards.js.map +1 -0
  40. package/build/utils/index.d.ts +7 -0
  41. package/build/utils/index.d.ts.map +1 -0
  42. package/build/utils/index.js +7 -0
  43. package/build/utils/index.js.map +1 -0
  44. package/build/utils/payload.d.ts +10 -0
  45. package/build/utils/payload.d.ts.map +1 -0
  46. package/build/utils/payload.js +55 -0
  47. package/build/utils/payload.js.map +1 -0
  48. package/build/utils/server.d.ts +10 -0
  49. package/build/utils/server.d.ts.map +1 -0
  50. package/build/utils/server.js +56 -0
  51. package/build/utils/server.js.map +1 -0
  52. package/package.json +62 -0
  53. package/src/consts.ts +7 -0
  54. package/src/errors.ts +35 -0
  55. package/src/helper.ts +89 -0
  56. package/src/index.ts +6 -0
  57. package/src/server.ts +183 -0
  58. package/src/types.ts +26 -0
  59. package/src/utils/context.ts +9 -0
  60. package/src/utils/error.ts +18 -0
  61. package/src/utils/guards.ts +75 -0
  62. package/src/utils/index.ts +7 -0
  63. package/src/utils/payload.ts +62 -0
  64. package/src/utils/server.ts +70 -0
  65. package/tsconfig.json +15 -0
  66. package/tsconfig.tsbuildinfo +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,613 @@
1
+ # @owlmeans/server-api
2
+
3
+ Server-side API framework for OwlMeans Common applications. This package provides a comprehensive HTTP server implementation built on Fastify, with seamless integration into the OwlMeans module system, authentication, validation, and error handling.
4
+
5
+ ## Overview
6
+
7
+ The `@owlmeans/server-api` package is a high-level server framework that extends the OwlMeans ecosystem with HTTP API capabilities. It provides:
8
+
9
+ - **Fastify-based HTTP Server**: High-performance HTTP server with comprehensive middleware
10
+ - **Module Integration**: Seamless integration with OwlMeans modules for route handling
11
+ - **Authentication & Authorization**: Built-in support for authentication guards and gates
12
+ - **Request/Response Handling**: Structured request/response processing with validation
13
+ - **File Upload Support**: Multipart file upload handling with configurable limits
14
+ - **Error Management**: Comprehensive error handling with resilient error system
15
+ - **Security Features**: CORS, Helmet, and security middleware integration
16
+ - **Context Propagation**: Request-scoped context management throughout the request lifecycle
17
+
18
+ This package is part of the OwlMeans "quadra" pattern as a server-side implementation, complementing client-side packages and providing the backend foundation for fullstack applications.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @owlmeans/server-api
24
+ ```
25
+
26
+ ## Dependencies
27
+
28
+ This package requires and integrates with:
29
+ - `@owlmeans/server-context`: Server context management
30
+ - `@owlmeans/server-module`: Server-side module system
31
+ - `@owlmeans/auth-common`: Authentication middleware
32
+ - `@owlmeans/module`: Core module system
33
+ - `@owlmeans/route`: Routing infrastructure
34
+ - `@owlmeans/api`: API utilities and constants
35
+ - `fastify`: High-performance HTTP server
36
+
37
+ ## Core Concepts
38
+
39
+ ### API Server Service
40
+
41
+ The API server is implemented as an OwlMeans service that manages a Fastify instance, handles module registration, and provides lifecycle management.
42
+
43
+ ### Module-based Routing
44
+
45
+ Routes are defined through OwlMeans modules, which are automatically registered with the Fastify server and processed according to their configuration.
46
+
47
+ ### Context Propagation
48
+
49
+ Each request receives a context that contains authentication information, services, and can be modified by intermediate modules throughout the request lifecycle.
50
+
51
+ ### Request/Response Abstraction
52
+
53
+ The framework provides abstracted request/response objects that hide Fastify-specific details while providing access to the underlying objects when needed.
54
+
55
+ ## API Reference
56
+
57
+ ### Types
58
+
59
+ #### `ApiServer`
60
+ Main server service interface that manages the Fastify instance.
61
+
62
+ ```typescript
63
+ interface ApiServer extends InitializedService {
64
+ server: FastifyInstance
65
+ layers: [Layer.System]
66
+ listen(): Promise<void>
67
+ }
68
+ ```
69
+
70
+ **Properties:**
71
+ - `server`: The underlying Fastify instance
72
+ - `layers`: Service operates at System layer
73
+
74
+ **Methods:**
75
+ - `listen(): Promise<void>`: Starts the HTTP server and listens for connections
76
+
77
+ #### `Request`
78
+ Type alias for Fastify request objects.
79
+
80
+ ```typescript
81
+ interface Request extends FastifyRequest {}
82
+ ```
83
+
84
+ #### `Response`
85
+ Type alias for Fastify reply objects.
86
+
87
+ ```typescript
88
+ interface Response extends FastifyReply {}
89
+ ```
90
+
91
+ #### `Config`
92
+ Server configuration interface.
93
+
94
+ ```typescript
95
+ interface Config extends ServerConfig {}
96
+ ```
97
+
98
+ #### `Context<C extends Config>`
99
+ Server context interface with API server capabilities.
100
+
101
+ ```typescript
102
+ interface Context<C extends Config = Config> extends ServerContext<C>, ApiServerAppend {}
103
+ ```
104
+
105
+ #### `ApiServerAppend`
106
+ Interface for contexts that provide API server access.
107
+
108
+ ```typescript
109
+ interface ApiServerAppend {
110
+ getApiServer(): ApiServer
111
+ }
112
+ ```
113
+
114
+ ### Factory Functions
115
+
116
+ #### `createApiServer(alias: string): ApiServer`
117
+
118
+ Creates an API server service instance with comprehensive middleware and configuration.
119
+
120
+ **Parameters:**
121
+ - `alias`: Service alias for registration
122
+
123
+ **Returns:** ApiServer instance
124
+
125
+ **Features:**
126
+ - Fastify server with logging
127
+ - CORS support with configurable origins
128
+ - Security headers via Helmet
129
+ - File upload support with multipart
130
+ - Raw body parsing
131
+ - AJV validation with format support
132
+ - Module-based routing
133
+ - Authentication integration
134
+ - Error handling
135
+
136
+ **Example:**
137
+ ```typescript
138
+ import { createApiServer } from '@owlmeans/server-api'
139
+
140
+ const apiServer = createApiServer('main-api')
141
+ ```
142
+
143
+ ### Helper Functions
144
+
145
+ #### `handleBody<T>(handler: (payload: T, ctx: BasicContext, req: AbstractRequest) => Promise<any>): RefedModuleHandler`
146
+
147
+ Creates a module handler that processes request body data.
148
+
149
+ **Parameters:**
150
+ - `handler`: Function that processes the request body
151
+
152
+ **Returns:** Module handler function
153
+
154
+ **Example:**
155
+ ```typescript
156
+ import { handleBody } from '@owlmeans/server-api'
157
+
158
+ const createUserHandler = handleBody<CreateUserRequest>(async (payload, ctx, req) => {
159
+ const userService = ctx.service('user')
160
+ return await userService.create(payload)
161
+ })
162
+ ```
163
+
164
+ #### `handleParams<T>(handler: (payload: T, ctx: BasicContext, req: AbstractRequest) => Promise<any>): RefedModuleHandler`
165
+
166
+ Creates a module handler that processes URL parameters.
167
+
168
+ **Parameters:**
169
+ - `handler`: Function that processes the URL parameters
170
+
171
+ **Returns:** Module handler function
172
+
173
+ **Example:**
174
+ ```typescript
175
+ import { handleParams } from '@owlmeans/server-api'
176
+
177
+ const getUserHandler = handleParams<{ id: string }>(async (params, ctx) => {
178
+ const userService = ctx.service('user')
179
+ return await userService.get(params.id)
180
+ })
181
+ ```
182
+
183
+ #### `handleRequest(handler: (req: AbstractRequest, ctx: BasicContext, res?: AbstractResponse) => Promise<any>): RefedModuleHandler`
184
+
185
+ Creates a module handler that processes the full request object.
186
+
187
+ **Parameters:**
188
+ - `handler`: Function that processes the request
189
+
190
+ **Returns:** Module handler function
191
+
192
+ **Example:**
193
+ ```typescript
194
+ import { handleRequest } from '@owlmeans/server-api'
195
+
196
+ const customHandler = handleRequest(async (req, ctx, res) => {
197
+ // Custom request processing logic
198
+ return { message: 'Custom response' }
199
+ })
200
+ ```
201
+
202
+ #### `handleIntermediate(handler: (req: AbstractRequest, ctx: BasicContext) => Promise<BasicContext | null>): RefedModuleHandler`
203
+
204
+ Creates an intermediate module handler that can modify the request context.
205
+
206
+ **Parameters:**
207
+ - `handler`: Function that processes request and potentially modifies context
208
+
209
+ **Returns:** Module handler function
210
+
211
+ **Example:**
212
+ ```typescript
213
+ import { handleIntermediate } from '@owlmeans/server-api'
214
+
215
+ const authMiddleware = handleIntermediate(async (req, ctx) => {
216
+ // Add authentication data to context
217
+ const modifiedContext = await addAuthToContext(ctx, req)
218
+ return modifiedContext
219
+ })
220
+ ```
221
+
222
+ #### `extractUploadedFile(req: AbstractRequest): Promise<UploadedFile | undefined>`
223
+
224
+ Extracts an uploaded file from a multipart request.
225
+
226
+ **Parameters:**
227
+ - `req`: Abstract request object
228
+
229
+ **Returns:** Promise resolving to uploaded file or undefined
230
+
231
+ **Example:**
232
+ ```typescript
233
+ import { extractUploadedFile } from '@owlmeans/server-api'
234
+
235
+ const uploadHandler = handleRequest(async (req, ctx) => {
236
+ const file = await extractUploadedFile(req)
237
+ if (file) {
238
+ // Process uploaded file
239
+ return { filename: file.filename, size: file.file.bytesRead }
240
+ }
241
+ throw new NoFileError()
242
+ })
243
+ ```
244
+
245
+ ### Error Types
246
+
247
+ The package provides comprehensive error classes for API-specific failures:
248
+
249
+ #### `AuthFailedError`
250
+ Error for authentication failures.
251
+
252
+ ```typescript
253
+ class AuthFailedError extends ApiError {
254
+ constructor(message: string = 'error')
255
+ }
256
+ ```
257
+
258
+ #### `AccessError`
259
+ Error for authorization/access failures.
260
+
261
+ ```typescript
262
+ class AccessError extends ApiError {
263
+ constructor(message: string = 'error')
264
+ }
265
+ ```
266
+
267
+ #### `NoFileError`
268
+ Error when an expected file upload is missing.
269
+
270
+ ```typescript
271
+ class NoFileError extends ApiError {
272
+ constructor()
273
+ }
274
+ ```
275
+
276
+ ### Constants
277
+
278
+ #### Server Configuration
279
+ ```typescript
280
+ const DEFAULT_ALIAS = 'api-server' // Default service alias
281
+ const PORT = 80 // Default HTTP port
282
+ const CLOSED_HOST = '127.0.0.1' // Localhost binding
283
+ const OPENED_HOST = '0.0.0.0' // Open binding for external access
284
+ ```
285
+
286
+ ### Utility Functions
287
+
288
+ Available in the `/utils` subpackage:
289
+
290
+ #### Request/Response Utilities
291
+ - `provideRequest(alias, req, provision?)`: Creates AbstractRequest from Fastify request
292
+ - `executeResponse(response, reply, throwOnError?)`: Executes AbstractResponse with Fastify reply
293
+
294
+ #### Server Utilities
295
+ - `canServeModule(context, module)`: Determines if a module can be served by the API server
296
+ - `createServerHandler(module, location)`: Creates Fastify route handler from OwlMeans module
297
+
298
+ #### Guard Utilities
299
+ - `authorize(context, module, req, reply)`: Handles authentication and authorization for modules
300
+
301
+ ## Usage Examples
302
+
303
+ ### Basic API Server Setup
304
+
305
+ ```typescript
306
+ import { createApiServer } from '@owlmeans/server-api'
307
+ import { makeServerContext } from '@owlmeans/server-context'
308
+ import { AppType, Layer } from '@owlmeans/context'
309
+
310
+ // Create server context
311
+ const context = makeServerContext({
312
+ service: 'my-api',
313
+ type: AppType.Backend,
314
+ layer: Layer.Service,
315
+ services: {
316
+ 'my-api': {
317
+ host: 'localhost',
318
+ port: 3000,
319
+ opened: true
320
+ }
321
+ }
322
+ })
323
+
324
+ // Create and register API server
325
+ const apiServer = createApiServer('main-api')
326
+ context.registerService(apiServer)
327
+
328
+ // Initialize and start server
329
+ await context.configure().init()
330
+ await apiServer.listen()
331
+ ```
332
+
333
+ ### Module-based API Endpoints
334
+
335
+ ```typescript
336
+ import { module } from '@owlmeans/module'
337
+ import { route, backend, RouteMethod } from '@owlmeans/route'
338
+ import { handleBody, handleParams } from '@owlmeans/server-api'
339
+
340
+ // Create API modules
341
+ const getUserModule = module(
342
+ route('get-user', '/api/users/:id', backend(null, RouteMethod.GET)),
343
+ {
344
+ handle: handleParams<{ id: string }>(async (params, ctx) => {
345
+ const userService = ctx.service('user')
346
+ return await userService.get(params.id)
347
+ })
348
+ }
349
+ )
350
+
351
+ const createUserModule = module(
352
+ route('create-user', '/api/users', backend(null, RouteMethod.POST)),
353
+ {
354
+ handle: handleBody<CreateUserRequest>(async (payload, ctx) => {
355
+ const userService = ctx.service('user')
356
+ return await userService.create(payload)
357
+ }),
358
+ filter: {
359
+ body: {
360
+ type: 'object',
361
+ properties: {
362
+ name: { type: 'string' },
363
+ email: { type: 'string', format: 'email' }
364
+ },
365
+ required: ['name', 'email']
366
+ }
367
+ }
368
+ }
369
+ )
370
+
371
+ // Register modules with context
372
+ context.registerModule(getUserModule)
373
+ context.registerModule(createUserModule)
374
+ ```
375
+
376
+ ### Authentication and Authorization
377
+
378
+ ```typescript
379
+ import { guard, gate } from '@owlmeans/module'
380
+
381
+ // Protected endpoint with authentication guard
382
+ const protectedModule = module(
383
+ route('protected', '/api/admin/users', backend(null, RouteMethod.GET)),
384
+ {
385
+ ...guard('auth'), // Requires authentication
386
+ ...gate('admin', ['users']), // Requires admin gate with users permission
387
+ handle: handleRequest(async (req, ctx) => {
388
+ // Only authenticated admin users can access this
389
+ return { message: 'Admin access granted' }
390
+ })
391
+ }
392
+ )
393
+ ```
394
+
395
+ ### File Upload Handling
396
+
397
+ ```typescript
398
+ import { extractUploadedFile, NoFileError } from '@owlmeans/server-api'
399
+
400
+ const uploadModule = module(
401
+ route('upload', '/api/upload', backend(null, RouteMethod.POST)),
402
+ {
403
+ handle: handleRequest(async (req, ctx) => {
404
+ const file = await extractUploadedFile(req)
405
+ if (!file) {
406
+ throw new NoFileError()
407
+ }
408
+
409
+ // Process the uploaded file
410
+ const fileData = await file.toBuffer()
411
+
412
+ return {
413
+ filename: file.filename,
414
+ size: fileData.length,
415
+ mimetype: file.mimetype
416
+ }
417
+ })
418
+ }
419
+ )
420
+ ```
421
+
422
+ ### Intermediate Middleware
423
+
424
+ ```typescript
425
+ import { handleIntermediate } from '@owlmeans/server-api'
426
+
427
+ // Logging middleware
428
+ const loggingModule = module(
429
+ route('logging', '/api/*'),
430
+ {
431
+ sticky: true, // Apply to all routes
432
+ handle: handleIntermediate(async (req, ctx) => {
433
+ console.log(`${req.method} ${req.path}`)
434
+ return ctx // Return context unchanged
435
+ })
436
+ }
437
+ )
438
+
439
+ // Authentication middleware
440
+ const authModule = module(
441
+ route('auth-middleware', '/api/auth/*'),
442
+ {
443
+ sticky: true,
444
+ handle: handleIntermediate(async (req, ctx) => {
445
+ // Extract and validate auth token
446
+ const authToken = req.headers.authorization
447
+ if (authToken) {
448
+ const authService = ctx.service('auth')
449
+ const auth = await authService.validate(authToken)
450
+ // Add auth to request for downstream handlers
451
+ req.auth = auth
452
+ }
453
+ return ctx
454
+ })
455
+ }
456
+ )
457
+ ```
458
+
459
+ ### Error Handling
460
+
461
+ ```typescript
462
+ import { AuthFailedError, AccessError } from '@owlmeans/server-api'
463
+
464
+ const secureModule = module(
465
+ route('secure', '/api/secure', backend()),
466
+ {
467
+ handle: handleRequest(async (req, ctx) => {
468
+ // Check authentication
469
+ if (!req.auth) {
470
+ throw new AuthFailedError('Authentication required')
471
+ }
472
+
473
+ // Check authorization
474
+ if (req.auth.role !== 'admin') {
475
+ throw new AccessError('Admin access required')
476
+ }
477
+
478
+ return { message: 'Secure data' }
479
+ })
480
+ }
481
+ )
482
+ ```
483
+
484
+ ### Custom Server Configuration
485
+
486
+ ```typescript
487
+ import { createApiServer } from '@owlmeans/server-api'
488
+
489
+ const apiServer = createApiServer('custom-api')
490
+
491
+ // Access underlying Fastify instance for custom configuration
492
+ apiServer.server.register(async (fastify) => {
493
+ // Custom Fastify plugins or configuration
494
+ fastify.addHook('preHandler', async (request, reply) => {
495
+ // Custom pre-handler logic
496
+ })
497
+ })
498
+
499
+ // Custom listen configuration
500
+ const context = makeServerContext({
501
+ services: {
502
+ 'custom-api': {
503
+ host: '0.0.0.0',
504
+ port: 8080,
505
+ opened: true,
506
+ internalPort: 8080 // Use different internal port
507
+ }
508
+ }
509
+ })
510
+ ```
511
+
512
+ ## Advanced Features
513
+
514
+ ### Context Modification
515
+
516
+ Intermediate modules can modify the request context, allowing for dynamic service injection and request preprocessing:
517
+
518
+ ```typescript
519
+ const contextModifier = handleIntermediate(async (req, ctx) => {
520
+ // Dynamically add services based on request
521
+ if (req.headers['x-tenant-id']) {
522
+ const tenantCtx = await createTenantContext(req.headers['x-tenant-id'])
523
+ return tenantCtx
524
+ }
525
+ return ctx
526
+ })
527
+ ```
528
+
529
+ ### Request Lifecycle
530
+
531
+ 1. **Pre-handler Hook**: Processes intermediate modules in order
532
+ 2. **Authentication**: Validates authentication guards
533
+ 3. **Authorization**: Checks authorization gates
534
+ 4. **Validation**: Validates request schema (body, params, query)
535
+ 5. **Handler Execution**: Executes module handler
536
+ 6. **Response Processing**: Formats and sends response
537
+
538
+ ### Server Configuration
539
+
540
+ The server automatically configures based on context service settings:
541
+
542
+ - `host`: Server host binding
543
+ - `port`: Server port
544
+ - `internalPort`: Alternative port for internal binding
545
+ - `opened`: Whether to bind to external interfaces (0.0.0.0) or localhost only
546
+
547
+ ## Integration with OwlMeans Ecosystem
548
+
549
+ ### Module Integration
550
+
551
+ ```typescript
552
+ import { modules } from '@owlmeans/server-module'
553
+
554
+ // Server modules are automatically processed by the API server
555
+ context.registerModules(modules)
556
+ ```
557
+
558
+ ### Authentication Integration
559
+
560
+ ```typescript
561
+ import { makeAuthService } from '@owlmeans/server-auth'
562
+
563
+ const authService = makeAuthService()
564
+ context.registerService(authService)
565
+
566
+ // Auth service is automatically used by authentication guards
567
+ ```
568
+
569
+ ### Resource Integration
570
+
571
+ ```typescript
572
+ import { createDbService } from '@owlmeans/mongo-resource'
573
+
574
+ const dbService = createDbService('mongo', config)
575
+ context.registerService(dbService)
576
+
577
+ // Database services are available in module handlers
578
+ ```
579
+
580
+ ## Performance Considerations
581
+
582
+ - **Fastify Framework**: High-performance HTTP server
583
+ - **Context Reuse**: Request contexts are reused where possible
584
+ - **Validation Caching**: AJV schemas are compiled once and cached
585
+ - **Middleware Pipeline**: Efficient middleware processing with early termination
586
+ - **File Upload Limits**: Configurable file size and count limits
587
+
588
+ ## Security Features
589
+
590
+ - **CORS Support**: Configurable cross-origin resource sharing
591
+ - **Helmet Integration**: Security headers middleware
592
+ - **Authentication Guards**: Built-in authentication checking
593
+ - **Authorization Gates**: Fine-grained permission checking
594
+ - **Input Validation**: Comprehensive request validation
595
+ - **Error Handling**: Secure error message handling
596
+
597
+ ## Best Practices
598
+
599
+ 1. **Module Organization**: Group related endpoints into logical modules
600
+ 2. **Error Handling**: Use appropriate error types for different failure modes
601
+ 3. **Validation**: Always validate input data using schema validation
602
+ 4. **Authentication**: Use authentication guards for protected endpoints
603
+ 5. **Authorization**: Implement fine-grained authorization with gates
604
+ 6. **File Uploads**: Configure appropriate file size limits
605
+ 7. **Context Management**: Use intermediate modules for cross-cutting concerns
606
+
607
+ ## Related Packages
608
+
609
+ - [`@owlmeans/server-context`](../server-context) - Server context management
610
+ - [`@owlmeans/server-module`](../server-module) - Server module system
611
+ - [`@owlmeans/auth-common`](../auth-common) - Authentication middleware
612
+ - [`@owlmeans/api`](../api) - API utilities and constants
613
+ - [`@owlmeans/module`](../module) - Core module system
package/build/.gitkeep ADDED
File without changes
@@ -0,0 +1,5 @@
1
+ export declare const DEFAULT_ALIAS = "api-server";
2
+ export declare const PORT = 80;
3
+ export declare const CLOSED_HOST = "127.0.0.1";
4
+ export declare const OPENED_HOST = "0.0.0.0";
5
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa,eAAe,CAAA;AAEzC,eAAO,MAAM,IAAI,KAAK,CAAA;AAEtB,eAAO,MAAM,WAAW,cAAc,CAAA;AACtC,eAAO,MAAM,WAAW,YAAY,CAAA"}
@@ -0,0 +1,5 @@
1
+ export const DEFAULT_ALIAS = 'api-server';
2
+ export const PORT = 80;
3
+ export const CLOSED_HOST = '127.0.0.1';
4
+ export const OPENED_HOST = '0.0.0.0';
5
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAA;AAEzC,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAA;AAEtB,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAA;AACtC,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { ApiError } from '@owlmeans/api';
2
+ export declare class AuthFailedError extends ApiError {
3
+ static typeName: string;
4
+ constructor(message?: string);
5
+ }
6
+ export declare class AccessError extends ApiError {
7
+ static typeName: string;
8
+ constructor(message?: string);
9
+ }
10
+ export declare class NoFileError extends ApiError {
11
+ static typeName: string;
12
+ constructor();
13
+ }
14
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAGxC,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,OAAuB,QAAQ,SAAoB;gBAEvC,OAAO,GAAE,MAAgB;CAItC;AAED,qBAAa,WAAY,SAAQ,QAAQ;IACvC,OAAuB,QAAQ,SAAsC;gBAEzD,OAAO,GAAE,MAAgB;CAItC;AAED,qBAAa,WAAY,SAAQ,QAAQ;IACvC,OAAuB,QAAQ,SAAgB;;CAMhD"}
@@ -0,0 +1,27 @@
1
+ import { ApiError } from '@owlmeans/api';
2
+ import { ResilientError } from '@owlmeans/error';
3
+ export class AuthFailedError extends ApiError {
4
+ static typeName = 'AuthFailedError';
5
+ constructor(message = 'error') {
6
+ super(`auth:${message}`);
7
+ this.type = AuthFailedError.typeName;
8
+ }
9
+ }
10
+ export class AccessError extends ApiError {
11
+ static typeName = `Access${AuthFailedError.typeName}`;
12
+ constructor(message = 'error') {
13
+ super(`access:${message}`);
14
+ this.type = AccessError.typeName;
15
+ }
16
+ }
17
+ export class NoFileError extends ApiError {
18
+ static typeName = 'NoFileError';
19
+ constructor() {
20
+ super('no file');
21
+ this.type = NoFileError.typeName;
22
+ }
23
+ }
24
+ ResilientError.registerErrorClass(AuthFailedError);
25
+ ResilientError.registerErrorClass(AccessError);
26
+ ResilientError.registerErrorClass(NoFileError);
27
+ //# sourceMappingURL=errors.js.map