@owlmeans/server-api 0.1.1 → 0.1.3
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/LICENSE +1 -1
- package/README.md +36 -572
- package/build/helper.d.ts +6 -6
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +4 -4
- package/build/helper.js.map +1 -1
- package/build/server.d.ts.map +1 -1
- package/build/server.js +6 -4
- package/build/server.js.map +1 -1
- package/build/utils/guards.d.ts +2 -2
- package/build/utils/guards.d.ts.map +1 -1
- package/build/utils/guards.js +2 -2
- package/build/utils/guards.js.map +1 -1
- package/build/utils/payload.d.ts +1 -1
- package/build/utils/payload.d.ts.map +1 -1
- package/build/utils/payload.js +4 -4
- package/build/utils/payload.js.map +1 -1
- package/build/utils/server.d.ts +4 -4
- package/build/utils/server.d.ts.map +1 -1
- package/build/utils/server.js +1 -1
- package/build/utils/server.js.map +1 -1
- package/package.json +13 -11
- package/src/helper.ts +10 -10
- package/src/server.ts +8 -5
- package/src/utils/guards.ts +6 -6
- package/src/utils/payload.ts +5 -5
- package/src/utils/server.ts +6 -6
- package/tsconfig.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 OwlMeans Common — Fullstack typescript framework
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,613 +1,77 @@
|
|
|
1
1
|
# @owlmeans/server-api
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Fastify-based HTTP/WebSocket server with handler wrappers for the OwlMeans module system.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
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.
|
|
7
|
+
- `handleBody`, `handleParams`, `handleRequest` wrap business logic with context injection and error handling
|
|
8
|
+
- Built on [Fastify](https://fastify.dev/) — registered modules become Fastify routes automatically
|
|
9
|
+
- `createApiServer` / `appendApiServer` initialize the HTTP server in a context
|
|
10
|
+
- Not typically used directly — import handlers from `@owlmeans/server-app`
|
|
19
11
|
|
|
20
12
|
## Installation
|
|
21
13
|
|
|
22
14
|
```bash
|
|
23
|
-
|
|
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
|
-
})
|
|
15
|
+
bun add @owlmeans/server-api
|
|
220
16
|
```
|
|
221
17
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
Extracts an uploaded file from a multipart request.
|
|
225
|
-
|
|
226
|
-
**Parameters:**
|
|
227
|
-
- `req`: Abstract request object
|
|
18
|
+
## Usage
|
|
228
19
|
|
|
229
|
-
|
|
20
|
+
Handler functions called via `elevate()` in modules:
|
|
230
21
|
|
|
231
|
-
**Example:**
|
|
232
22
|
```typescript
|
|
233
|
-
import {
|
|
23
|
+
import { handleBody, handleParams, handleRequest } from '@owlmeans/server-app'
|
|
234
24
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return { filename: file.filename, size: file.file.bytesRead }
|
|
240
|
-
}
|
|
241
|
-
throw new NoFileError()
|
|
25
|
+
// Body handler: receives parsed + validated body as first arg
|
|
26
|
+
export const create = handleBody<CreateProject>(async (payload, context, req) => {
|
|
27
|
+
const ctx = context as Context
|
|
28
|
+
return await ctx.project().create({ ...payload, entityId: req.auth!.entityId })
|
|
242
29
|
})
|
|
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
30
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
}
|
|
31
|
+
// Params handler: receives validated URL params as first arg
|
|
32
|
+
export const get = handleParams<{ id: string }>(async (params, context, req) => {
|
|
33
|
+
return await (context as Context).project().get(params.id)
|
|
322
34
|
})
|
|
323
35
|
|
|
324
|
-
//
|
|
325
|
-
const
|
|
326
|
-
|
|
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
|
-
}
|
|
36
|
+
// Request handler: receives the full AbstractRequest
|
|
37
|
+
export const health = handleRequest(async (req, context) => {
|
|
38
|
+
return { status: 'ok' }
|
|
509
39
|
})
|
|
510
40
|
```
|
|
511
41
|
|
|
512
|
-
##
|
|
513
|
-
|
|
514
|
-
### Context Modification
|
|
42
|
+
## API
|
|
515
43
|
|
|
516
|
-
|
|
44
|
+
### `handleBody<T>(handler): RefedModuleHandler`
|
|
517
45
|
|
|
46
|
+
Wraps a handler that receives the validated request body as the first argument.
|
|
518
47
|
```typescript
|
|
519
|
-
|
|
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
|
-
})
|
|
48
|
+
handler: (payload: T, ctx: Context, req: AbstractRequest) => Promise<any>
|
|
527
49
|
```
|
|
528
50
|
|
|
529
|
-
###
|
|
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
|
|
51
|
+
### `handleParams<T>(handler): RefedModuleHandler`
|
|
550
52
|
|
|
53
|
+
Wraps a handler that receives the validated URL params as the first argument.
|
|
551
54
|
```typescript
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
// Server modules are automatically processed by the API server
|
|
555
|
-
context.registerModules(modules)
|
|
55
|
+
handler: (payload: T, ctx: Context, req: AbstractRequest) => Promise<any>
|
|
556
56
|
```
|
|
557
57
|
|
|
558
|
-
###
|
|
58
|
+
### `handleRequest(handler): RefedModuleHandler`
|
|
559
59
|
|
|
60
|
+
Wraps a handler that receives the full request object.
|
|
560
61
|
```typescript
|
|
561
|
-
|
|
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
|
|
62
|
+
handler: (req: AbstractRequest, ctx: Context, res?: AbstractResponse) => Promise<any>
|
|
578
63
|
```
|
|
579
64
|
|
|
580
|
-
|
|
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
|
|
65
|
+
### `handleIntermediate(handler): RefedModuleHandler`
|
|
589
66
|
|
|
590
|
-
-
|
|
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
|
|
67
|
+
Wraps middleware-layer handlers that do not return a final response.
|
|
596
68
|
|
|
597
|
-
|
|
69
|
+
### `extractUploadedFile(req, fieldName): UploadedFile | null`
|
|
598
70
|
|
|
599
|
-
|
|
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
|
|
71
|
+
Extract a multipart-uploaded file from the request.
|
|
606
72
|
|
|
607
73
|
## Related Packages
|
|
608
74
|
|
|
609
|
-
- [`@owlmeans/server-
|
|
610
|
-
- [`@owlmeans/server-module`](../server-module)
|
|
611
|
-
- [`@owlmeans/
|
|
612
|
-
- [`@owlmeans/api`](../api) - API utilities and constants
|
|
613
|
-
- [`@owlmeans/module`](../module) - Core module system
|
|
75
|
+
- [`@owlmeans/server-app`](../server-app) — re-exports all handlers; preferred import point
|
|
76
|
+
- [`@owlmeans/server-module`](../server-module) — `elevate()` attaches handlers to modules
|
|
77
|
+
- [`@owlmeans/server-socket`](../server-socket) — WebSocket `handleConnection` counterpart
|
package/build/helper.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
|
-
import type { AbstractRequest, AbstractResponse } from '@owlmeans/
|
|
3
|
-
import type {
|
|
2
|
+
import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint';
|
|
3
|
+
import type { RefedEntrypointHandler } from '@owlmeans/server-entrypoint';
|
|
4
4
|
import type { Context } from './types.js';
|
|
5
5
|
import type { MultipartFile } from '@fastify/multipart';
|
|
6
|
-
export declare const handleBody: <T>(handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>) =>
|
|
7
|
-
export declare const handleParams: <T>(handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>) =>
|
|
8
|
-
export declare const handleRequest: (handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>, res?: AbstractResponse<any>) => Promise<any>) =>
|
|
9
|
-
export declare const handleIntermediate: (handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>) => Promise<BasicContext<BasicConfig> | null>) =>
|
|
6
|
+
export declare const handleBody: <T>(handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>) => RefedEntrypointHandler<AbstractResponse<any>>;
|
|
7
|
+
export declare const handleParams: <T>(handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>) => RefedEntrypointHandler<AbstractResponse<any>>;
|
|
8
|
+
export declare const handleRequest: (handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>, res?: AbstractResponse<any>) => Promise<any>) => RefedEntrypointHandler<AbstractResponse<any>>;
|
|
9
|
+
export declare const handleIntermediate: (handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>) => Promise<BasicContext<BasicConfig> | null>) => RefedEntrypointHandler<AbstractResponse<Context | null>>;
|
|
10
10
|
export declare const extractUploadedFile: <T extends {} = {}>(req: AbstractRequest<T>) => Promise<UploadedFile | undefined>;
|
|
11
11
|
export interface UploadedFile extends MultipartFile {
|
|
12
12
|
}
|
package/build/helper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGlE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGlE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzE,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAMvD,eAAO,MAAM,UAAU,EAAE,CAAC,CAAC,EACzB,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,GAAG,CAAC,KACxF,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAahD,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,CAAC,CAAC,EAC3B,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,GAAG,CAAC,KAExF,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAahD,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,CAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,KAC7G,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAWhD,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,CAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,KAC7G,sBAAsB,CAAC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAc3D,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAU,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,eAAe,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAItH,CAAA;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;CAAI"}
|
package/build/helper.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { assertContext } from '@owlmeans/context';
|
|
2
|
-
import {
|
|
2
|
+
import { EntrypointOutcome } from '@owlmeans/entrypoint';
|
|
3
3
|
const _castContextFromOriginal = (req, def) => {
|
|
4
4
|
return req.original._ctx ?? def;
|
|
5
5
|
};
|
|
6
6
|
export const handleBody = handler => ref => async (req, res) => {
|
|
7
7
|
const ctx = assertContext(ref.ref?.ctx);
|
|
8
8
|
try {
|
|
9
|
-
res.resolve(await handler(req.body, _castContextFromOriginal(req, ctx), req),
|
|
9
|
+
res.resolve(await handler(req.body, _castContextFromOriginal(req, ctx), req), EntrypointOutcome.Ok);
|
|
10
10
|
}
|
|
11
11
|
catch (e) {
|
|
12
12
|
res.reject(e);
|
|
@@ -16,7 +16,7 @@ export const handleBody = handler => ref => async (req, res) => {
|
|
|
16
16
|
export const handleParams = handler => ref => async (req, res) => {
|
|
17
17
|
const ctx = assertContext(ref.ref?.ctx);
|
|
18
18
|
try {
|
|
19
|
-
res.resolve(await handler(req.params, _castContextFromOriginal(req, ctx), req),
|
|
19
|
+
res.resolve(await handler(req.params, _castContextFromOriginal(req, ctx), req), EntrypointOutcome.Ok);
|
|
20
20
|
}
|
|
21
21
|
catch (e) {
|
|
22
22
|
res.reject(e);
|
|
@@ -26,7 +26,7 @@ export const handleParams = handler => ref => async (req, res) => {
|
|
|
26
26
|
export const handleRequest = handler => ref => async (req, res) => {
|
|
27
27
|
const ctx = assertContext(ref.ref?.ctx);
|
|
28
28
|
try {
|
|
29
|
-
res.resolve(await handler(req, _castContextFromOriginal(req, ctx), res),
|
|
29
|
+
res.resolve(await handler(req, _castContextFromOriginal(req, ctx), res), EntrypointOutcome.Ok);
|
|
30
30
|
}
|
|
31
31
|
catch (e) {
|
|
32
32
|
res.reject(e);
|
package/build/helper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAOxD,MAAM,wBAAwB,GAAG,CAAqE,GAAoB,EAAE,GAAM,EAAK,EAAE;IACvI,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAE8B,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxF,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,GAAG,CAAC,OAAO,CAAC,MAAM,OAAO,CACvB,GAAG,CAAC,IAAW,EACf,wBAAwB,CAAkB,GAAG,EAAE,GAAG,CAA8B,EAChF,GAAG,CACJ,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAG4B,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxF,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,GAAG,CAAC,OAAO,CAAC,MAAM,OAAO,CACvB,GAAG,CAAC,MAAa,EACjB,wBAAwB,CAAkB,GAAG,EAAE,GAAG,CAA8B,EAChF,GAAG,CACJ,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAE2B,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxF,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,GAAG,CAAC,OAAO,CAAC,MAAM,OAAO,CACvB,GAAG,EAAE,wBAAwB,CAAkB,GAAG,EAAE,GAAG,CAA8B,EAAE,GAAG,CAC3F,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAA;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAEiC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACnG,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,GAAG,EAAE,wBAAwB,CAAkB,GAAG,EAAE,GAAG,CAA8B,CACtF,CAAA;QACD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACrB,CAAC;QAED,OAAO,GAAG,CAAC,KAAK,CAAA;IAClB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAqB,GAAuB,EAAqC,EAAE;IACzH,MAAM,OAAO,GAAG,GAAG,CAAC,QAA0B,CAAA;IAE9C,OAAO,OAAO,CAAC,IAAI,EAAE,CAAA;AACvB,CAAC,CAAA"}
|
package/build/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiC5D,KAAK,MAAM,GAAG,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiC5D,KAAK,MAAM,GAAG,YAAY,CAAA;AAK1B,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,SAyI/C,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1E,KAAK,CAAC,EAAE,QAAO,MAAsB,KACpC,CAAC,GAAG,eAWN,CAAA"}
|
package/build/server.js
CHANGED
|
@@ -3,7 +3,7 @@ import { canServeModule, executeResponse, provideRequest } from './utils/index.j
|
|
|
3
3
|
import { DEFAULT_ALIAS, CLOSED_HOST, PORT, OPENED_HOST } from './consts.js';
|
|
4
4
|
import { RouteMethod } from '@owlmeans/route';
|
|
5
5
|
import { createServerHandler, fixFormatDates } from './utils/index.js';
|
|
6
|
-
import { provideResponse } from '@owlmeans/
|
|
6
|
+
import { provideResponse } from '@owlmeans/entrypoint';
|
|
7
7
|
import { TOKEN_UPDATE } from '@owlmeans/auth-common';
|
|
8
8
|
import Fastify from 'fastify';
|
|
9
9
|
import cors from '@fastify/cors';
|
|
@@ -23,12 +23,14 @@ const ajv = new Ajv({
|
|
|
23
23
|
});
|
|
24
24
|
formatsPlugin(ajv);
|
|
25
25
|
ajvErrors(ajv, { singleError: true });
|
|
26
|
+
const bodyLimit = 1024 * 1024 * 20;
|
|
26
27
|
export const createApiServer = (alias) => {
|
|
27
28
|
const location = `service:${alias}`;
|
|
28
29
|
const _assertContext = (context) => assertContext(context, location);
|
|
29
30
|
const service = createService(alias, {
|
|
30
31
|
server: Fastify({
|
|
31
32
|
logger: true,
|
|
33
|
+
bodyLimit,
|
|
32
34
|
/*{
|
|
33
35
|
transport: {
|
|
34
36
|
target: 'pino-pretty',
|
|
@@ -57,7 +59,7 @@ export const createApiServer = (alias) => {
|
|
|
57
59
|
}, service => async () => {
|
|
58
60
|
if (service.server.server.listening) {
|
|
59
61
|
await service.server.close();
|
|
60
|
-
service.server = Fastify({ logger: true });
|
|
62
|
+
service.server = Fastify({ logger: true, bodyLimit });
|
|
61
63
|
}
|
|
62
64
|
const context = _assertContext(service.ctx);
|
|
63
65
|
const server = service.server;
|
|
@@ -83,7 +85,7 @@ export const createApiServer = (alias) => {
|
|
|
83
85
|
server.addHook('preHandler', async (request, reply) => {
|
|
84
86
|
const context = _assertContext(service.ctx);
|
|
85
87
|
// We pass context further using fastify request object
|
|
86
|
-
request._ctx = await context.
|
|
88
|
+
request._ctx = await context.entrypoints().filter(module => canServeModule(context, module) && module.route.isIntermediate()).reduce(async (promise, module) => {
|
|
87
89
|
let context = await promise;
|
|
88
90
|
if (reply.sent) {
|
|
89
91
|
return context;
|
|
@@ -104,7 +106,7 @@ export const createApiServer = (alias) => {
|
|
|
104
106
|
return context;
|
|
105
107
|
}, Promise.resolve(context));
|
|
106
108
|
});
|
|
107
|
-
await Promise.all(context.
|
|
109
|
+
await Promise.all(context.entrypoints()
|
|
108
110
|
.filter(module => canServeModule(context, module) && !module.route.isIntermediate())
|
|
109
111
|
.map(async (module) => {
|
|
110
112
|
// await module.route.resolve(context as any)
|
package/build/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/build/utils/guards.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ServerEntrypoint } from '@owlmeans/server-entrypoint';
|
|
3
3
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
|
|
4
4
|
type Config = ServerConfig;
|
|
5
5
|
interface Context<C extends Config = Config> extends ServerContext<C> {
|
|
6
6
|
}
|
|
7
|
-
export declare const authorize: <C extends Config, T extends Context<C>>(context: T, module:
|
|
7
|
+
export declare const authorize: <C extends Config, T extends Context<C>>(context: T, module: ServerEntrypoint<FastifyRequest>, req: FastifyRequest, reply: FastifyReply) => Promise<[T, ServerEntrypoint<FastifyRequest>]>;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAK3E,KAAK,MAAM,GAAG,YAAY,CAAA;AAC1B,UAAU,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAI;AAEzE,eAAO,MAAM,SAAS,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EACpE,SAAS,CAAC,EAAE,QAAQ,gBAAgB,CAAC,cAAc,CAAC,EACpD,KAAK,cAAc,EAAE,OAAO,YAAY,KACvC,OAAO,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC,CA0D/C,CAAA"}
|
package/build/utils/guards.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isContextWithoutIds, Layer } from '@owlmeans/context';
|
|
2
|
-
import { provideResponse } from '@owlmeans/
|
|
2
|
+
import { provideResponse } from '@owlmeans/entrypoint';
|
|
3
3
|
import { executeResponse, provideRequest } from './payload.js';
|
|
4
4
|
import { AuthFailedError } from '../errors.js';
|
|
5
5
|
export const authorize = async (context, module, req, reply) => {
|
|
@@ -46,7 +46,7 @@ export const authorize = async (context, module, req, reply) => {
|
|
|
46
46
|
context = await context.updateContext(request.auth.entityId, Layer.Entity);
|
|
47
47
|
await context.waitForInitialized();
|
|
48
48
|
// We elevate module to the context level if it was changed
|
|
49
|
-
module = context.
|
|
49
|
+
module = context.entrypoint(module.alias);
|
|
50
50
|
await module.resolve();
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAI9D,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAI9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAM9C,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,OAAU,EAAE,MAAwC,EACpD,GAAmB,EAAE,KAAmB,EACQ,EAAE;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;IACjC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;QACvC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAEjD,IAAI,KAAK,GAA6B,SAAS,CAAA;QAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAiB,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACnD,IAAI,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC1C,KAAK,GAAG,MAAM,CAAA;YAChB,CAAC;YACD,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YACtC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,MAAK;YACP,CAAC;QACH,CAAC;QAED,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,eAAe,EAAE,CAAA;QAC7B,CAAC;QAED,MAAM,YAAY,GAAG,eAAe,CAAO,KAAK,CAAC,CAAA;QACjD,IAAI,CAAC,MAAM,KAAK,CAAC,MAAM,CAAU,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;QACD,eAAe,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;QAC1C,6EAA6E;QAC7E,oCAAoC;QACpC,6GAA6G;QAC7G,IAAI;QACJ,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC;QAClC,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,GAAW,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA;QACnC,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;YACnC,2DAA2D;YAC3D,IAAI,CAAC,mBAAmB,CAAC,OAAc,CAAC,EAAE,CAAC;gBACzC,MAAM,WAAW,CAAC,sDAAsD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACrH,CAAC;YAED,IAAI,mBAAmB,CAAC,OAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/E,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;gBAC/D,MAAM,OAAO,CAAC,kBAAkB,EAAE,CAAA;YACpC,CAAC;YACD,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;YAC1E,MAAM,OAAO,CAAC,kBAAkB,EAAE,CAAA;YAElC,2DAA2D;YAC3D,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACzC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QACxB,CAAC;IACH,CAAC;IACD,mCAAmC;IAClC,GAAW,CAAC,IAAI,GAAG,OAAO,CAAA;IAE3B,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC1B,CAAC,CAAA"}
|
package/build/utils/payload.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AbstractResponse, AbstractRequest } from '@owlmeans/
|
|
1
|
+
import type { AbstractResponse, AbstractRequest } from '@owlmeans/entrypoint';
|
|
2
2
|
import type { Request, Response } from '../types.js';
|
|
3
3
|
import type { AnySchemaObject } from 'ajv';
|
|
4
4
|
export declare const provideRequest: (alias: string, req: Request, provision?: boolean) => AbstractRequest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/utils/payload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/utils/payload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAE1C,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,EAAE,KAAK,OAAO,EAAE,YAAY,OAAO,KAAG,eAYjF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,UAAU,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,QAAQ,EAAE,eAAe,OAAO,SAmBxG,CAAA;AAGD,eAAO,MAAM,cAAc,GAAI,QAAQ,eAAe,oBAgBrD,CAAA"}
|
package/build/utils/payload.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EntrypointOutcome } from '@owlmeans/entrypoint';
|
|
2
2
|
import { ACCEPTED, CREATED, OK, SERVER_ERROR } from '@owlmeans/api';
|
|
3
3
|
export const provideRequest = (alias, req, provision) => {
|
|
4
4
|
provision = provision ?? false;
|
|
@@ -25,13 +25,13 @@ export const executeResponse = (response, reply, throwOnError) => {
|
|
|
25
25
|
}
|
|
26
26
|
else if (response.outcome != null) {
|
|
27
27
|
switch (response.outcome) {
|
|
28
|
-
case
|
|
28
|
+
case EntrypointOutcome.Accepted:
|
|
29
29
|
reply.code(ACCEPTED).send(response.value);
|
|
30
30
|
break;
|
|
31
|
-
case
|
|
31
|
+
case EntrypointOutcome.Created:
|
|
32
32
|
reply.code(CREATED).send(response.value);
|
|
33
33
|
break;
|
|
34
|
-
case
|
|
34
|
+
case EntrypointOutcome.Ok:
|
|
35
35
|
default:
|
|
36
36
|
reply.code(OK).send(response.value);
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/utils/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/utils/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAGnE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,GAAY,EAAE,SAAmB,EAAmB,EAAE;IAClG,SAAS,GAAG,SAAS,IAAI,KAAK,CAAA;IAC9B,OAAO;QACL,KAAK;QACL,IAAI,EAAG,GAAW,CAAC,KAAK,IAAI,SAAS;QACrC,MAAM,EAAE,GAAG,CAAC,MAA4D;QACxE,IAAI,EAAE,GAAG,CAAC,IAA2B;QACrC,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAA2D;QACtE,IAAI,EAAE,GAAG,CAAC,GAAG;QACb,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;KACtC,CAAA;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAI,QAA6B,EAAE,KAAe,EAAE,YAAsB,EAAE,EAAE;IAC3G,IAAI,QAAQ,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,YAAY,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,QAAQ,CAAC,KAAK,CAAA;QACtB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvD,CAAC;SAAM,IAAI,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;QACpC,QAAQ,QAAQ,CAAC,OAAO,EAAE,CAAC;YACzB,KAAK,iBAAiB,CAAC,QAAQ;gBAC7B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBACzC,MAAK;YACP,KAAK,iBAAiB,CAAC,OAAO;gBAC5B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBACxC,MAAK;YACP,KAAK,iBAAiB,CAAC,EAAE,CAAC;YAC1B;gBACE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAGD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAuB,EAAE,EAAE;IACxD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAA;YACtB,MAAM,CAAC,MAAM,GAAG,WAAW,CAAA;YAC3B,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;gBAC5B,OAAO,MAAM,CAAC,QAAQ,CAAA;YACxB,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YACrC,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,WAAW,CACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,KAAwB,CAAC,CAAC,CAAC,CACzG,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
package/build/utils/server.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { ServerEntrypoint } from '@owlmeans/server-entrypoint';
|
|
3
|
+
import type { CommonEntrypoint } from '@owlmeans/entrypoint';
|
|
4
4
|
import type { ServerContext, ServerConfig } from '@owlmeans/server-context';
|
|
5
5
|
type Config = ServerConfig;
|
|
6
6
|
type Context = ServerContext<Config>;
|
|
7
|
-
export declare const canServeModule: (context: Context, module:
|
|
8
|
-
export declare const createServerHandler: (module:
|
|
7
|
+
export declare const canServeModule: (context: Context, module: CommonEntrypoint) => module is ServerEntrypoint<unknown>;
|
|
8
|
+
export declare const createServerHandler: (module: ServerEntrypoint<FastifyRequest>, location: string) => (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
9
9
|
export {};
|
|
10
10
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/utils/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE3D,OAAO,KAAK,EAAgB,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/utils/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE3D,OAAO,KAAK,EAAgB,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAG5D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQ3E,KAAK,MAAM,GAAG,YAAY,CAAA;AAC1B,KAAK,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;AAEpC,eAAO,MAAM,cAAc,GAAI,SAAS,OAAO,EAAE,QAAQ,gBAAgB,KAAG,MAAM,IAAI,gBAAgB,CAAC,OAAO,CAY7G,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,QAAQ,gBAAgB,CAAC,cAAc,CAAC,EAAE,UAAU,MAAM,MACrF,KAAK,cAAc,EAAE,OAAO,YAAY,kBAoC9C,CAAA"}
|
package/build/utils/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AppType } from '@owlmeans/context';
|
|
2
2
|
import { assertContext } from '@owlmeans/context';
|
|
3
|
-
import { provideResponse } from '@owlmeans/
|
|
3
|
+
import { provideResponse } from '@owlmeans/entrypoint';
|
|
4
4
|
import { ResilientError } from '@owlmeans/error';
|
|
5
5
|
import { OK } from '@owlmeans/api';
|
|
6
6
|
import { handleError } from './error.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/utils/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAIjD,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/utils/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"build": "tsc -b",
|
|
@@ -31,15 +32,15 @@
|
|
|
31
32
|
"@fastify/helmet": "^12.0.1",
|
|
32
33
|
"@fastify/middie": "^9.0.2",
|
|
33
34
|
"@fastify/multipart": "^9.0.1",
|
|
34
|
-
"@owlmeans/api": "^0.1.
|
|
35
|
-
"@owlmeans/auth": "^0.1.
|
|
36
|
-
"@owlmeans/auth-common": "^0.1.
|
|
37
|
-
"@owlmeans/context": "^0.1.
|
|
38
|
-
"@owlmeans/error": "^0.1.
|
|
39
|
-
"@owlmeans/
|
|
40
|
-
"@owlmeans/route": "^0.1.
|
|
41
|
-
"@owlmeans/server-context": "^0.1.
|
|
42
|
-
"@owlmeans/server-
|
|
35
|
+
"@owlmeans/api": "^0.1.3",
|
|
36
|
+
"@owlmeans/auth": "^0.1.3",
|
|
37
|
+
"@owlmeans/auth-common": "^0.1.3",
|
|
38
|
+
"@owlmeans/context": "^0.1.3",
|
|
39
|
+
"@owlmeans/error": "^0.1.3",
|
|
40
|
+
"@owlmeans/entrypoint": "^0.1.3",
|
|
41
|
+
"@owlmeans/route": "^0.1.3",
|
|
42
|
+
"@owlmeans/server-context": "^0.1.3",
|
|
43
|
+
"@owlmeans/server-entrypoint": "^0.1.3",
|
|
43
44
|
"ajv-errors": "^3.0.0",
|
|
44
45
|
"fastify": "^5.0.0",
|
|
45
46
|
"fastify-raw-body": "^5.0.0",
|
|
@@ -50,10 +51,11 @@
|
|
|
50
51
|
"ajv-formats": "*"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
54
|
+
"@owlmeans/dep-config": "workspace:*",
|
|
53
55
|
"@types/node": "^24.10.1",
|
|
54
56
|
"nodemon": "^3.1.11",
|
|
55
57
|
"npm-check": "^6.0.1",
|
|
56
|
-
"typescript": "^
|
|
58
|
+
"typescript": "^6.0.2"
|
|
57
59
|
},
|
|
58
60
|
"publishConfig": {
|
|
59
61
|
"access": "public"
|
package/src/helper.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import type { BasicConfig, BasicContext } from '@owlmeans/context'
|
|
3
3
|
import { assertContext } from '@owlmeans/context'
|
|
4
|
-
import {
|
|
5
|
-
import type { AbstractRequest, AbstractResponse } from '@owlmeans/
|
|
6
|
-
import type {
|
|
4
|
+
import { EntrypointOutcome } from '@owlmeans/entrypoint'
|
|
5
|
+
import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint'
|
|
6
|
+
import type { RefedEntrypointHandler } from '@owlmeans/server-entrypoint'
|
|
7
7
|
import type { Config, Context } from './types.js'
|
|
8
8
|
import type { FastifyRequest } from 'fastify'
|
|
9
9
|
import type { MultipartFile } from '@fastify/multipart'
|
|
@@ -14,14 +14,14 @@ const _castContextFromOriginal = <C extends BasicConfig, T extends BasicContext<
|
|
|
14
14
|
|
|
15
15
|
export const handleBody: <T>(
|
|
16
16
|
handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>
|
|
17
|
-
) =>
|
|
17
|
+
) => RefedEntrypointHandler<AbstractResponse<any>> = handler => ref => async (req, res) => {
|
|
18
18
|
const ctx = assertContext(ref.ref?.ctx) as Context
|
|
19
19
|
try {
|
|
20
20
|
res.resolve(await handler(
|
|
21
21
|
req.body as any,
|
|
22
22
|
_castContextFromOriginal<Config, Context>(req, ctx) as BasicContext<BasicConfig>,
|
|
23
23
|
req,
|
|
24
|
-
),
|
|
24
|
+
), EntrypointOutcome.Ok)
|
|
25
25
|
} catch (e) {
|
|
26
26
|
res.reject(e as Error)
|
|
27
27
|
}
|
|
@@ -32,14 +32,14 @@ export const handleBody: <T>(
|
|
|
32
32
|
export const handleParams: <T>(
|
|
33
33
|
handler: (payload: T, ctx: BasicContext<BasicConfig>, req: AbstractRequest) => Promise<any>
|
|
34
34
|
// @TODO Here and everywher it looks like AbstractResponse is messed up here instead of abstract request
|
|
35
|
-
) =>
|
|
35
|
+
) => RefedEntrypointHandler<AbstractResponse<any>> = handler => ref => async (req, res) => {
|
|
36
36
|
const ctx = assertContext(ref.ref?.ctx) as Context
|
|
37
37
|
try {
|
|
38
38
|
res.resolve(await handler(
|
|
39
39
|
req.params as any,
|
|
40
40
|
_castContextFromOriginal<Config, Context>(req, ctx) as BasicContext<BasicConfig>,
|
|
41
41
|
req,
|
|
42
|
-
),
|
|
42
|
+
), EntrypointOutcome.Ok)
|
|
43
43
|
} catch (e) {
|
|
44
44
|
res.reject(e as Error)
|
|
45
45
|
}
|
|
@@ -49,12 +49,12 @@ export const handleParams: <T>(
|
|
|
49
49
|
|
|
50
50
|
export const handleRequest: (
|
|
51
51
|
handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>, res?: AbstractResponse<any>) => Promise<any>
|
|
52
|
-
) =>
|
|
52
|
+
) => RefedEntrypointHandler<AbstractResponse<any>> = handler => ref => async (req, res) => {
|
|
53
53
|
const ctx = assertContext(ref.ref?.ctx) as Context
|
|
54
54
|
try {
|
|
55
55
|
res.resolve(await handler(
|
|
56
56
|
req, _castContextFromOriginal<Config, Context>(req, ctx) as BasicContext<BasicConfig>, res
|
|
57
|
-
),
|
|
57
|
+
), EntrypointOutcome.Ok)
|
|
58
58
|
} catch (e) {
|
|
59
59
|
res.reject(e as Error)
|
|
60
60
|
}
|
|
@@ -64,7 +64,7 @@ export const handleRequest: (
|
|
|
64
64
|
|
|
65
65
|
export const handleIntermediate: (
|
|
66
66
|
handler: (payload: AbstractRequest, ctx: BasicContext<BasicConfig>) => Promise<BasicContext<BasicConfig> | null>
|
|
67
|
-
) =>
|
|
67
|
+
) => RefedEntrypointHandler<AbstractResponse<Context | null>> = handler => ref => async (req, res) => {
|
|
68
68
|
const ctx = assertContext(ref.ref?.ctx) as Context
|
|
69
69
|
try {
|
|
70
70
|
const result = await handler(
|
package/src/server.ts
CHANGED
|
@@ -3,10 +3,10 @@ import type { ApiServer, ApiServerAppend } from './types.js'
|
|
|
3
3
|
import { Layer, assertContext, createService } from '@owlmeans/context'
|
|
4
4
|
import { canServeModule, executeResponse, provideRequest } from './utils/index.js'
|
|
5
5
|
import { DEFAULT_ALIAS, CLOSED_HOST, PORT, OPENED_HOST } from './consts.js'
|
|
6
|
-
import type {
|
|
6
|
+
import type { ServerEntrypoint } from '@owlmeans/server-entrypoint'
|
|
7
7
|
import { RouteMethod } from '@owlmeans/route'
|
|
8
8
|
import { createServerHandler, fixFormatDates } from './utils/index.js'
|
|
9
|
-
import { provideResponse } from '@owlmeans/
|
|
9
|
+
import { provideResponse } from '@owlmeans/entrypoint'
|
|
10
10
|
import { TOKEN_UPDATE } from '@owlmeans/auth-common'
|
|
11
11
|
|
|
12
12
|
import Fastify from 'fastify'
|
|
@@ -35,6 +35,8 @@ ajvErrors(ajv, { singleError: true })
|
|
|
35
35
|
type Config = ServerConfig
|
|
36
36
|
type Context = ServerContext<Config>
|
|
37
37
|
|
|
38
|
+
const bodyLimit = 1024 * 1024 * 20
|
|
39
|
+
|
|
38
40
|
export const createApiServer = (alias: string): ApiServer => {
|
|
39
41
|
const location = `service:${alias}`
|
|
40
42
|
const _assertContext = (context: Context | undefined): Context => assertContext<Config, Context>(context, location)
|
|
@@ -42,6 +44,7 @@ export const createApiServer = (alias: string): ApiServer => {
|
|
|
42
44
|
const service = createService<ApiServer>(alias, {
|
|
43
45
|
server: Fastify({
|
|
44
46
|
logger: true,
|
|
47
|
+
bodyLimit,
|
|
45
48
|
/*{
|
|
46
49
|
transport: {
|
|
47
50
|
target: 'pino-pretty',
|
|
@@ -75,7 +78,7 @@ export const createApiServer = (alias: string): ApiServer => {
|
|
|
75
78
|
}, service => async () => {
|
|
76
79
|
if (service.server.server.listening) {
|
|
77
80
|
await service.server.close()
|
|
78
|
-
service.server = Fastify({ logger: true })
|
|
81
|
+
service.server = Fastify({ logger: true, bodyLimit })
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
const context = _assertContext(service.ctx as Context)
|
|
@@ -105,7 +108,7 @@ export const createApiServer = (alias: string): ApiServer => {
|
|
|
105
108
|
server.addHook('preHandler', async (request, reply) => {
|
|
106
109
|
const context = _assertContext(service.ctx as Context);
|
|
107
110
|
// We pass context further using fastify request object
|
|
108
|
-
(request as any)._ctx = await context.
|
|
111
|
+
(request as any)._ctx = await context.entrypoints<ServerEntrypoint<FastifyRequest>>().filter(
|
|
109
112
|
module => canServeModule(context, module) && module.route.isIntermediate()
|
|
110
113
|
).reduce<Promise<Context>>(async (promise, module) => {
|
|
111
114
|
let context = await promise
|
|
@@ -131,7 +134,7 @@ export const createApiServer = (alias: string): ApiServer => {
|
|
|
131
134
|
})
|
|
132
135
|
|
|
133
136
|
await Promise.all(
|
|
134
|
-
context.
|
|
137
|
+
context.entrypoints<ServerEntrypoint<FastifyRequest>>()
|
|
135
138
|
.filter(module => canServeModule(context, module) && !module.route.isIntermediate())
|
|
136
139
|
.map(async module => {
|
|
137
140
|
// await module.route.resolve(context as any)
|
package/src/utils/guards.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isContextWithoutIds, Layer } from '@owlmeans/context'
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
3
|
-
import type {
|
|
4
|
-
import type { GuardService } from '@owlmeans/
|
|
5
|
-
import { provideResponse } from '@owlmeans/
|
|
3
|
+
import type { ServerEntrypoint } from '@owlmeans/server-entrypoint'
|
|
4
|
+
import type { GuardService } from '@owlmeans/entrypoint'
|
|
5
|
+
import { provideResponse } from '@owlmeans/entrypoint'
|
|
6
6
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
|
|
7
7
|
import { executeResponse, provideRequest } from './payload.js'
|
|
8
8
|
import { AuthFailedError } from '../errors.js'
|
|
@@ -12,9 +12,9 @@ type Config = ServerConfig
|
|
|
12
12
|
interface Context<C extends Config = Config> extends ServerContext<C> { }
|
|
13
13
|
|
|
14
14
|
export const authorize = async <C extends Config, T extends Context<C>>(
|
|
15
|
-
context: T, module:
|
|
15
|
+
context: T, module: ServerEntrypoint<FastifyRequest>,
|
|
16
16
|
req: FastifyRequest, reply: FastifyReply
|
|
17
|
-
): Promise<[T,
|
|
17
|
+
): Promise<[T, ServerEntrypoint<FastifyRequest>]> => {
|
|
18
18
|
const guards = module.getGuards()
|
|
19
19
|
if (guards.length > 0) {
|
|
20
20
|
const response = provideResponse(reply)
|
|
@@ -64,7 +64,7 @@ export const authorize = async <C extends Config, T extends Context<C>>(
|
|
|
64
64
|
await context.waitForInitialized()
|
|
65
65
|
|
|
66
66
|
// We elevate module to the context level if it was changed
|
|
67
|
-
module = context.
|
|
67
|
+
module = context.entrypoint(module.alias)
|
|
68
68
|
await module.resolve()
|
|
69
69
|
}
|
|
70
70
|
}
|
package/src/utils/payload.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { AbstractResponse, AbstractRequest } from '@owlmeans/
|
|
1
|
+
import { EntrypointOutcome } from '@owlmeans/entrypoint'
|
|
2
|
+
import type { AbstractResponse, AbstractRequest } from '@owlmeans/entrypoint'
|
|
3
3
|
import type { Request, Response } from '../types.js'
|
|
4
4
|
import { ACCEPTED, CREATED, OK, SERVER_ERROR } from '@owlmeans/api'
|
|
5
5
|
import type { AnySchemaObject } from 'ajv'
|
|
@@ -29,13 +29,13 @@ export const executeResponse = <T>(response: AbstractResponse<T>, reply: Respons
|
|
|
29
29
|
reply.code(SERVER_ERROR).send(response.error.message)
|
|
30
30
|
} else if (response.outcome != null) {
|
|
31
31
|
switch (response.outcome) {
|
|
32
|
-
case
|
|
32
|
+
case EntrypointOutcome.Accepted:
|
|
33
33
|
reply.code(ACCEPTED).send(response.value)
|
|
34
34
|
break
|
|
35
|
-
case
|
|
35
|
+
case EntrypointOutcome.Created:
|
|
36
36
|
reply.code(CREATED).send(response.value)
|
|
37
37
|
break
|
|
38
|
-
case
|
|
38
|
+
case EntrypointOutcome.Ok:
|
|
39
39
|
default:
|
|
40
40
|
reply.code(OK).send(response.value)
|
|
41
41
|
}
|
package/src/utils/server.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AppType } from '@owlmeans/context'
|
|
2
2
|
import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
3
3
|
import { assertContext } from '@owlmeans/context'
|
|
4
|
-
import type { FixerService,
|
|
5
|
-
import type {
|
|
6
|
-
import type { GateService } from '@owlmeans/
|
|
7
|
-
import { provideResponse } from '@owlmeans/
|
|
4
|
+
import type { FixerService, ServerEntrypoint } from '@owlmeans/server-entrypoint'
|
|
5
|
+
import type { CommonEntrypoint } from '@owlmeans/entrypoint'
|
|
6
|
+
import type { GateService } from '@owlmeans/entrypoint'
|
|
7
|
+
import { provideResponse } from '@owlmeans/entrypoint'
|
|
8
8
|
import type { ServerContext, ServerConfig } from '@owlmeans/server-context'
|
|
9
9
|
import { ResilientError } from '@owlmeans/error'
|
|
10
10
|
import { OK } from '@owlmeans/api'
|
|
@@ -16,7 +16,7 @@ import { RouteProtocols } from '@owlmeans/route'
|
|
|
16
16
|
type Config = ServerConfig
|
|
17
17
|
type Context = ServerContext<Config>
|
|
18
18
|
|
|
19
|
-
export const canServeModule = (context: Context, module:
|
|
19
|
+
export const canServeModule = (context: Context, module: CommonEntrypoint): module is ServerEntrypoint<unknown> => {
|
|
20
20
|
if (module.route.route.type !== AppType.Backend) {
|
|
21
21
|
return false
|
|
22
22
|
}
|
|
@@ -30,7 +30,7 @@ export const canServeModule = (context: Context, module: CommonModule): module i
|
|
|
30
30
|
return 'isIntermediate' in module.route
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export const createServerHandler = (module:
|
|
33
|
+
export const createServerHandler = (module: ServerEntrypoint<FastifyRequest>, location: string) =>
|
|
34
34
|
async (req: FastifyRequest, reply: FastifyReply) => {
|
|
35
35
|
// We passed context using fastify request object
|
|
36
36
|
let context = assertContext<Config, Context>((req as any)._ctx, location)
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": [
|
|
3
|
-
"
|
|
3
|
+
"@owlmeans/dep-config/tsconfig.base.json",
|
|
4
|
+
"@owlmeans/dep-config/tsconfig.node.json"
|
|
4
5
|
],
|
|
5
6
|
"compilerOptions": {
|
|
6
|
-
"rootDir": "./src/",
|
|
7
|
-
"outDir": "./build/"
|
|
8
|
-
"moduleResolution": "Bundler",
|
|
7
|
+
"rootDir": "./src/",
|
|
8
|
+
"outDir": "./build/"
|
|
9
9
|
},
|
|
10
10
|
"exclude": [
|
|
11
11
|
"./dist/**/*",
|
|
12
12
|
"./build/**/*",
|
|
13
13
|
"./*.ts"
|
|
14
14
|
]
|
|
15
|
-
}
|
|
15
|
+
}
|