alado 1.11.0 → 2.0.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.
- package/README.md +525 -11
- package/dist/alado-server/alado-server.d.ts +1 -0
- package/dist/alado-server/alado-server.js +2 -0
- package/dist/alado-server/alado-server.js.map +1 -1
- package/dist/constants/default-id.d.ts +1 -0
- package/dist/constants/default-id.js +5 -0
- package/dist/constants/default-id.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/decorators/define-request.d.ts +3 -0
- package/dist/decorators/define-request.js +22 -0
- package/dist/decorators/define-request.js.map +1 -0
- package/dist/decorators/define-response.d.ts +2 -0
- package/dist/decorators/define-response.js +18 -0
- package/dist/decorators/define-response.js.map +1 -0
- package/dist/decorators/document-property.d.ts +2 -0
- package/dist/decorators/document-property.js +21 -0
- package/dist/decorators/document-property.js.map +1 -0
- package/dist/decorators/file-upload-property.d.ts +2 -0
- package/dist/decorators/file-upload-property.js +17 -0
- package/dist/decorators/file-upload-property.js.map +1 -0
- package/dist/decorators/http.d.ts +7 -0
- package/dist/decorators/http.js +72 -0
- package/dist/decorators/http.js.map +1 -0
- package/dist/decorators/index.d.ts +8 -0
- package/dist/decorators/index.js +25 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/initialize-application.d.ts +3 -0
- package/dist/decorators/initialize-application.js +27 -0
- package/dist/decorators/initialize-application.js.map +1 -0
- package/dist/decorators/initialize-injector.d.ts +1 -0
- package/dist/decorators/initialize-injector.js +17 -0
- package/dist/decorators/initialize-injector.js.map +1 -0
- package/dist/decorators/validate-property.d.ts +2 -0
- package/dist/decorators/validate-property.js +22 -0
- package/dist/decorators/validate-property.js.map +1 -0
- package/dist/decorators/with-auth.d.ts +2 -0
- package/dist/decorators/with-auth.js +15 -0
- package/dist/decorators/with-auth.js.map +1 -0
- package/dist/dto/alado-server-error.d.ts +2 -2
- package/dist/dto/index.d.ts +1 -0
- package/dist/dto/index.js +1 -0
- package/dist/dto/index.js.map +1 -1
- package/dist/dto/open-api-doc-object.d.ts +4 -0
- package/dist/dto/open-api-doc-object.js +3 -0
- package/dist/dto/open-api-doc-object.js.map +1 -0
- package/dist/factory/open-api-doc-factory.js +5 -8
- package/dist/factory/open-api-doc-factory.js.map +1 -1
- package/dist/helpers/api-doc/doc-object-setter.d.ts +2 -0
- package/dist/helpers/api-doc/doc-object-setter.js +25 -0
- package/dist/helpers/api-doc/doc-object-setter.js.map +1 -0
- package/dist/helpers/api-doc/index.d.ts +1 -0
- package/dist/helpers/api-doc/index.js +18 -0
- package/dist/helpers/api-doc/index.js.map +1 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/parser/body-parser.d.ts +2 -2
- package/dist/helpers/parser/body-parser.js +10 -2
- package/dist/helpers/parser/body-parser.js.map +1 -1
- package/dist/helpers/validate/alado-options/validate-alado-options.js +18 -5
- package/dist/helpers/validate/alado-options/validate-alado-options.js.map +1 -1
- package/dist/helpers/validate/context/validate-context.js +1 -1
- package/dist/helpers/validate/context/validate-context.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/injector/index.d.ts +1 -0
- package/dist/injector/index.js +6 -0
- package/dist/injector/index.js.map +1 -0
- package/dist/injector/injector.d.ts +6 -0
- package/dist/{global → injector}/injector.js +2 -1
- package/dist/injector/injector.js.map +1 -0
- package/dist/options/alado-server-options.d.ts +2 -0
- package/dist/options/context-options.d.ts +14 -7
- package/dist/options/http-decorator-options.d.ts +7 -0
- package/dist/options/http-decorator-options.js +3 -0
- package/dist/options/http-decorator-options.js.map +1 -0
- package/dist/options/index.d.ts +3 -0
- package/dist/options/index.js +3 -0
- package/dist/options/index.js.map +1 -1
- package/dist/options/initialize-application-options.d.ts +6 -0
- package/dist/options/initialize-application-options.js +3 -0
- package/dist/options/initialize-application-options.js.map +1 -0
- package/dist/options/injector-options.d.ts +11 -0
- package/dist/{global/index.js → options/injector-options.js} +1 -1
- package/dist/options/injector-options.js.map +1 -0
- package/dist/options/request-processor-options.d.ts +1 -0
- package/dist/request-processor/request-processor.js +2 -2
- package/dist/request-processor/request-processor.js.map +1 -1
- package/package.json +1 -1
- package/dist/global/index.d.ts +0 -1
- package/dist/global/index.js.map +0 -1
- package/dist/global/injector.d.ts +0 -4
- package/dist/global/injector.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,12 +5,524 @@ Its main difference from most similar well-known frameworks is that with a minim
|
|
|
5
5
|
it provides out-of-the-box such fully-functioning features as routing, CORS, automatic API documentation (Open API 3.0),
|
|
6
6
|
parsing query and path parameters, and the request body, file uploading, request authentication, etc.
|
|
7
7
|
|
|
8
|
+
# Documentation for version 2.0.0 and above:
|
|
9
|
+
Version 2.0.0 comes with decorators that simplify the project structure and minimize the amount of code you need to write.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
There is an example of the API creating with Alado (version >= 2.0.0):
|
|
13
|
+
[https://github.com/databikers/alado-decorators-api-example](https://github.com/databikers/alado-decorators-api-example)
|
|
14
|
+
|
|
15
|
+
## Use inside controllers the next decorators:
|
|
16
|
+
|
|
17
|
+
### HTTP Method Decorators
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
get(path: string, options: HttpDecoratorOptions = {})
|
|
21
|
+
post(path: string, options: HttpDecoratorOptions = {})
|
|
22
|
+
put(path: string, options: HttpDecoratorOptions = {})
|
|
23
|
+
patch(path: string, options: HttpDecoratorOptions = {})
|
|
24
|
+
del(path: string, options: HttpDecoratorOptions = {})
|
|
25
|
+
head(path: string, options: HttpDecoratorOptions = {})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Arguments
|
|
29
|
+
- **path**: Route string (e.g., `/users/:id`).
|
|
30
|
+
- **options**: `HttpDecoratorOptions` object, may include:
|
|
31
|
+
- `appId`: Identifier of the application instance.
|
|
32
|
+
- `title`: A descriptive name of the endpoint.
|
|
33
|
+
- `description`: Documentation text for the endpoint.
|
|
34
|
+
- `tags`: Array of tags for grouping in OpenAPI docs.
|
|
35
|
+
- `isHidden`: Boolean flag to hide the endpoint from OpenAPI output
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### `defineRequest` decorator
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
defineRequest(request: Partial<Record<keyof [Request](#request), AnyClass>>)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Arguments
|
|
46
|
+
- **request**: A partial mapping of keys from [Request](#request) to your DTO classes.
|
|
47
|
+
- Keys can include:
|
|
48
|
+
- `headers`, `query`, `path`, `body`: each a record of property definitions.
|
|
49
|
+
- `files`: mapping of [FilePropertyDefinition](#filepropertydefinition).
|
|
50
|
+
- `auth`: authentication data mapping.
|
|
51
|
+
- Each value points to a class that uses specific DTO decorators to define how that part of the request should be validated and documented.
|
|
52
|
+
|
|
53
|
+
#### `Request`
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
interface Request {
|
|
57
|
+
request: IncomingMessage;
|
|
58
|
+
ip?: string;
|
|
59
|
+
origin?: string;
|
|
60
|
+
method?: HttpMethod;
|
|
61
|
+
url?: string;
|
|
62
|
+
auth?: Record<string, any>;
|
|
63
|
+
path?: Record<string, string>;
|
|
64
|
+
headers?: IncomingHttpHeaders;
|
|
65
|
+
query?: Record<string, any>;
|
|
66
|
+
body?: Record<string, any>;
|
|
67
|
+
rawBody?: string;
|
|
68
|
+
files?: Record<string, { stream: Readable; size: number; mimetype: string }>;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### `defineResponse` decorator
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
defineResponse(response: [Response](#response)<any>)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Arguments
|
|
81
|
+
- **response**: Response schema definition, including:
|
|
82
|
+
- `title`: Short descriptive title.
|
|
83
|
+
- `description`: Explanation of the response.
|
|
84
|
+
- `statusCode`: HTTP status code.
|
|
85
|
+
- `headers`: Mapping of header names to values.
|
|
86
|
+
- `body`: Response body object (may be an instance of some DTO or class).
|
|
87
|
+
|
|
88
|
+
#### `Response`
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
interface Response<T> {
|
|
92
|
+
title?: string;
|
|
93
|
+
description?: string;
|
|
94
|
+
statusCode: number;
|
|
95
|
+
headers?: Record<string, string>;
|
|
96
|
+
body?: T;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### `withAuth` decorator
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
withAuth(requestAuthentication: [RequestAuthentication](#requestauthentication))
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Arguments
|
|
108
|
+
- **requestAuthentication**: Defines authentication requirements, including:
|
|
109
|
+
- `inputProperty`: Field name in request used for auth input.
|
|
110
|
+
- `outputProperty`: Field name in request to store auth result.
|
|
111
|
+
- `handler`: Function to transform/verify authentication value.
|
|
112
|
+
- `handlerContext`: Optional context object passed to handler.
|
|
113
|
+
- `required`: Boolean indicating if authentication is mandatory.
|
|
114
|
+
- `error`: Error object to use when authentication fails.
|
|
115
|
+
|
|
116
|
+
#### `RequestAuthentication`
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
interface RequestAuthentication {
|
|
120
|
+
inputProperty: string;
|
|
121
|
+
outputProperty: string;
|
|
122
|
+
handler: (value: any) => any | Promise<any>;
|
|
123
|
+
handlerContext?: any;
|
|
124
|
+
required: boolean;
|
|
125
|
+
error: AladoServerError;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { RequestAuthentication } from 'alado';
|
|
132
|
+
import { DataStore } from '@data-store';
|
|
133
|
+
|
|
134
|
+
export const bearerAuth: RequestAuthentication = {
|
|
135
|
+
required: true,
|
|
136
|
+
inputProperty: 'headers.x-api-key',
|
|
137
|
+
outputProperty: 'auth.user',
|
|
138
|
+
handler(value: string) {
|
|
139
|
+
return DataStore.bearerAuth(value);
|
|
140
|
+
},
|
|
141
|
+
error: {
|
|
142
|
+
statusCode: 401,
|
|
143
|
+
message: 'Unauthorized',
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `AladoServerError`
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
type AladoServerError = {
|
|
153
|
+
statusCode: number;
|
|
154
|
+
message: string;
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
Example of controller:
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
export class UserController {
|
|
164
|
+
@post('/user', { tags: ['User'] })
|
|
165
|
+
@defineResponse({
|
|
166
|
+
statusCode: 201,
|
|
167
|
+
title: 'User',
|
|
168
|
+
headers: { 'Content-Type': 'application/json' },
|
|
169
|
+
body: exampleUserDto,
|
|
170
|
+
})
|
|
171
|
+
@defineRequest({ body: CredentialsDto })
|
|
172
|
+
public async create(req: Request) {
|
|
173
|
+
const { body } = req;
|
|
174
|
+
const user = DataStore.signUp(body as CredentialsDto);
|
|
175
|
+
return {
|
|
176
|
+
statusCode: 201,
|
|
177
|
+
headers: { 'Content-Type': 'application/json' },
|
|
178
|
+
body: user,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@patch('/user/:id', { tags: ['User'] })
|
|
183
|
+
@withAuth(bearerAuth)
|
|
184
|
+
@defineResponse({
|
|
185
|
+
statusCode: 200,
|
|
186
|
+
title: 'User',
|
|
187
|
+
headers: { 'Content-Type': 'application/json' },
|
|
188
|
+
body: exampleUserDto,
|
|
189
|
+
})
|
|
190
|
+
@defineRequest({ body: UserDto, path: Id })
|
|
191
|
+
public async update(req: Request) {
|
|
192
|
+
const isMyId = this.isMyId(req);
|
|
193
|
+
if (!isMyId) {
|
|
194
|
+
return {
|
|
195
|
+
statusCode: 403,
|
|
196
|
+
headers: { 'Content-Type': 'application/json' },
|
|
197
|
+
body: { message: 'Access denied' },
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const { path, body } = req;
|
|
201
|
+
const user = DataStore.getUser(path.id);
|
|
202
|
+
if (user) {
|
|
203
|
+
DataStore.setUser(path.id, body as UserDto);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
statusCode: user ? 200 : 404,
|
|
207
|
+
headers: { 'Content-Type': 'application/json' },
|
|
208
|
+
body: DataStore.getUser(path.id) || { message: 'Not Found' },
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@post('/user/:id/avatar', { tags: ['User'] })
|
|
213
|
+
@withAuth(bearerAuth)
|
|
214
|
+
@defineResponse({
|
|
215
|
+
statusCode: 200,
|
|
216
|
+
title: 'User',
|
|
217
|
+
headers: { 'Content-Type': 'application/json' },
|
|
218
|
+
body: exampleUserDto,
|
|
219
|
+
})
|
|
220
|
+
@defineRequest({ path: Id, files: UserFilesDto })
|
|
221
|
+
public setAvatar(req: Request) {
|
|
222
|
+
const isMyId = this.isMyId(req);
|
|
223
|
+
if (!isMyId) {
|
|
224
|
+
return {
|
|
225
|
+
statusCode: 403,
|
|
226
|
+
headers: { 'Content-Type': 'application/json' },
|
|
227
|
+
body: { message: 'Access denied' },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const { path, files } = req;
|
|
231
|
+
const user = DataStore.getUser(path.id);
|
|
232
|
+
if (!user) {
|
|
233
|
+
return {
|
|
234
|
+
statusCode: 404,
|
|
235
|
+
headers: { 'Content-Type': 'application/json' },
|
|
236
|
+
body: { message: 'Not Found' },
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const { avatar } = files;
|
|
240
|
+
const writeStream = createWriteStream(`${process.cwd()}/uploads/user-${path.id}-avatar.png`, {
|
|
241
|
+
encoding: 'latin1',
|
|
242
|
+
});
|
|
243
|
+
avatar.stream.pipe(writeStream);
|
|
244
|
+
return {
|
|
245
|
+
statusCode: 202,
|
|
246
|
+
headers: { 'Content-Type': 'application/json' },
|
|
247
|
+
body: {},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Use these decorators inside DTO classes:
|
|
257
|
+
|
|
258
|
+
### `fileUploadProperty`
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
fileUploadProperty(filePropertyDefinition: [FilePropertyDefinition](#filepropertydefinition))
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Arguments
|
|
265
|
+
- **filePropertyDefinition**: Object describing file upload rules, including:
|
|
266
|
+
- `mimetypes`: Array of allowed MIME types.
|
|
267
|
+
- `maxSize`: Maximum file size (bytes).
|
|
268
|
+
- `required`: Whether the file must be provided.
|
|
269
|
+
- `mimetypeError`, `maxSizeError`, `requiredError`: Error objects describing validation failures.
|
|
270
|
+
|
|
271
|
+
#### `FilePropertyDefinition`
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
interface FilePropertyDefinition {
|
|
275
|
+
mimetypes: string[];
|
|
276
|
+
maxSize: number;
|
|
277
|
+
required: boolean;
|
|
278
|
+
mimetypeError: AladoServerError;
|
|
279
|
+
maxSizeError: AladoServerError;
|
|
280
|
+
requiredError: AladoServerError;
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### `documentProperty`
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
documentProperty(propertyDocumentation: [PropertyDocumentation](#propertydocumentation))
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### Arguments
|
|
293
|
+
- **propertyDocumentation**: Documentation metadata for a property, including:
|
|
294
|
+
- `schema`: JSON Schema–like definition (`type`, `format`, validation structure).
|
|
295
|
+
- `description`: Human-readable explanation.
|
|
296
|
+
- `example`: Example value.
|
|
297
|
+
|
|
298
|
+
#### `PropertyDocumentation`
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
interface PropertyDocumentation {
|
|
302
|
+
schema: PropertyDefinitionSchema;
|
|
303
|
+
description?: string;
|
|
304
|
+
example?: any;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### `PropertyDefinitionSchema`
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
interface PropertyDefinitionSchema {
|
|
312
|
+
type?: string;
|
|
313
|
+
format?: string;
|
|
314
|
+
default?: any;
|
|
315
|
+
$ref?: string;
|
|
316
|
+
nullable?: boolean;
|
|
317
|
+
readOnly?: boolean;
|
|
318
|
+
writeOnly?: boolean;
|
|
319
|
+
deprecated?: boolean;
|
|
320
|
+
enum?: any[];
|
|
321
|
+
oneOf?: Array<PropertyDefinitionSchema>;
|
|
322
|
+
anyOf?: Array<PropertyDefinitionSchema>;
|
|
323
|
+
allOf?: Array<PropertyDefinitionSchema>;
|
|
324
|
+
not?: Array<PropertyDefinitionSchema>;
|
|
325
|
+
properties?: Record<string, PropertyDefinitionSchema>;
|
|
326
|
+
additionalProperties?: PropertyDefinitionSchema;
|
|
327
|
+
minProperties?: number;
|
|
328
|
+
maxProperties?: number;
|
|
329
|
+
minimum?: number;
|
|
330
|
+
maximum?: number;
|
|
331
|
+
exclusiveMinimum?: number;
|
|
332
|
+
exclusiveMaximum?: number;
|
|
333
|
+
multipleOf?: number;
|
|
334
|
+
minLength?: number;
|
|
335
|
+
maxLength?: number;
|
|
336
|
+
pattern?: string;
|
|
337
|
+
items?: PropertyDefinitionSchema;
|
|
338
|
+
minItems?: number;
|
|
339
|
+
maxItems?: number;
|
|
340
|
+
uniqueItems?: boolean;
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
### `validateProperty`
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
validateProperty(propertyValidation: [PropertyValidation](#propertyvalidation))
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Arguments
|
|
353
|
+
- **propertyValidation**: Validation rules, including:
|
|
354
|
+
- `required`: Whether the property is mandatory.
|
|
355
|
+
- `handler`: Function to validate the property value (sync or async).
|
|
356
|
+
- `error`: Error object returned when validation fails.
|
|
357
|
+
|
|
358
|
+
#### `PropertyValidation`
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
interface PropertyValidation {
|
|
362
|
+
required?: boolean;
|
|
363
|
+
handler: (value: any) => boolean | Promise<boolean>; // throws error when returns false
|
|
364
|
+
error: AladoServerError;
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
DTOs examples:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { validateProperty, documentProperty } from 'alado';
|
|
373
|
+
|
|
374
|
+
export class Id {
|
|
375
|
+
@validateProperty({
|
|
376
|
+
required: true,
|
|
377
|
+
handler: async (value: any) => idValidator(value),
|
|
378
|
+
error: {
|
|
379
|
+
statusCode: 400,
|
|
380
|
+
message: 'Invalid id',
|
|
381
|
+
},
|
|
382
|
+
})
|
|
383
|
+
@documentProperty({
|
|
384
|
+
schema: {
|
|
385
|
+
type: 'string',
|
|
386
|
+
},
|
|
387
|
+
example: '7ef5ed25-53b1-432f-96ec-8e35d830eb9c',
|
|
388
|
+
description: 'User Id',
|
|
389
|
+
})
|
|
390
|
+
id: string = '7ef5ed25-53b1-432f-96ec-8e35d830eb9c';
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
import { fileUploadProperty } from 'alado';
|
|
398
|
+
|
|
399
|
+
export class UserFilesDto {
|
|
400
|
+
@fileUploadProperty({
|
|
401
|
+
mimetypes: ['image/png'],
|
|
402
|
+
maxSize: 1048576,
|
|
403
|
+
required: true,
|
|
404
|
+
maxSizeError: {
|
|
405
|
+
statusCode: 413,
|
|
406
|
+
message: 'The avatar should not be larger than 1MB',
|
|
407
|
+
},
|
|
408
|
+
mimetypeError: {
|
|
409
|
+
statusCode: 415,
|
|
410
|
+
message: 'The avatar should be a PNG image',
|
|
411
|
+
},
|
|
412
|
+
requiredError: {
|
|
413
|
+
statusCode: 400,
|
|
414
|
+
message: 'The avatar file is required',
|
|
415
|
+
},
|
|
416
|
+
})
|
|
417
|
+
avatar: string = '/path/to/image.png';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
import { validateProperty, documentProperty } from 'alado';
|
|
424
|
+
|
|
425
|
+
export class CredentialsDto {
|
|
426
|
+
@validateProperty({
|
|
427
|
+
required: true,
|
|
428
|
+
handler: async (value: any) => emailValidator(value),
|
|
429
|
+
error: {
|
|
430
|
+
statusCode: 400,
|
|
431
|
+
message: 'Invalid email',
|
|
432
|
+
},
|
|
433
|
+
})
|
|
434
|
+
@documentProperty({
|
|
435
|
+
schema: {
|
|
436
|
+
type: 'string',
|
|
437
|
+
},
|
|
438
|
+
example: 'example@example.com',
|
|
439
|
+
description: 'User email',
|
|
440
|
+
})
|
|
441
|
+
email: string = 'example@example.com';
|
|
442
|
+
|
|
443
|
+
@validateProperty({
|
|
444
|
+
required: true,
|
|
445
|
+
handler: async (value: any) => passwordValidator(value),
|
|
446
|
+
error: {
|
|
447
|
+
statusCode: 400,
|
|
448
|
+
message: 'Invalid password',
|
|
449
|
+
},
|
|
450
|
+
})
|
|
451
|
+
@documentProperty({
|
|
452
|
+
schema: {
|
|
453
|
+
type: 'string',
|
|
454
|
+
},
|
|
455
|
+
example: 'securePassword',
|
|
456
|
+
description: 'User password',
|
|
457
|
+
})
|
|
458
|
+
password: string = 'securePassword';
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export const credentialsDto = new CredentialsDto();
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## Initialize the application
|
|
468
|
+
|
|
469
|
+
Finally, use the `initializeApplication` function to get an instance you would like to run:
|
|
470
|
+
|
|
471
|
+
```ts
|
|
472
|
+
import { initializeApplication } from 'alado';
|
|
473
|
+
import { aladoServerOptions } from '@config';
|
|
474
|
+
import { UserController } from '@user';
|
|
475
|
+
|
|
476
|
+
export const app = initializeApplication({
|
|
477
|
+
serverOptions: aladoServerOptions,
|
|
478
|
+
controllers: [UserController]
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
app.start(() => console.log('Application has been successfully started'));
|
|
482
|
+
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### Arguments
|
|
486
|
+
- **initializeApplicationOptions**: Object containing:
|
|
487
|
+
- **serverOptions** ([AladoServerOptions](#aladoserveroptions)): Configuration for starting the server (e.g., `appId`, port, logger).
|
|
488
|
+
- **controllers**: Array of controller classes to initialize at startup.
|
|
489
|
+
|
|
490
|
+
#### `InitializeApplicationOptions`
|
|
491
|
+
|
|
492
|
+
```ts
|
|
493
|
+
interface InitializeApplicationOptions {
|
|
494
|
+
serverOptions: AladoServerOptions;
|
|
495
|
+
controllers: AnyClass[];
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### `AladoServerOptions`
|
|
500
|
+
|
|
501
|
+
```ts
|
|
502
|
+
interface AladoServerOptions {
|
|
503
|
+
appId?: string;
|
|
504
|
+
port?: number;
|
|
505
|
+
logger?: AladoServerLogger;
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
#### `AladoServerLogger`
|
|
510
|
+
|
|
511
|
+
```ts
|
|
512
|
+
interface AladoServerLogger {
|
|
513
|
+
log: (...args: any[]) => void;
|
|
514
|
+
error: (error: Error) => void;
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
There is an example of the API creating with Alado (version < 2.0.0):
|
|
521
|
+
|
|
8
522
|
The basis of use is a combination of interface simplicity and separation of the “routine” part of writing API
|
|
9
523
|
from business logic implementation - due to a declarative approach to describing all request parameters
|
|
10
524
|
in the form of static reusable structures.
|
|
11
525
|
|
|
12
|
-
There is an example of the API creating with Alado:
|
|
13
|
-
|
|
14
526
|
[https://github.com/databikers/alado-api-example](https://github.com/databikers/alado-api-example)
|
|
15
527
|
|
|
16
528
|
1. Installation
|
|
@@ -32,7 +544,7 @@ const app: AladoServer = new AladoServer({
|
|
|
32
544
|
allowedHeaders: ['Authorization'],
|
|
33
545
|
exposeHeaders: ['x-total-count'],
|
|
34
546
|
},
|
|
35
|
-
|
|
547
|
+
documentProperty: {
|
|
36
548
|
enable: true,
|
|
37
549
|
route: '/open-api',
|
|
38
550
|
info: {
|
|
@@ -42,6 +554,7 @@ const app: AladoServer = new AladoServer({
|
|
|
42
554
|
},
|
|
43
555
|
},
|
|
44
556
|
verbose: true,
|
|
557
|
+
maxBodySizeBytes: 1024,
|
|
45
558
|
});
|
|
46
559
|
```
|
|
47
560
|
|
|
@@ -84,6 +597,7 @@ const app = new AladoServer({
|
|
|
84
597
|
},
|
|
85
598
|
},
|
|
86
599
|
verbose: true,
|
|
600
|
+
maxBodySizeBytes: 1024,
|
|
87
601
|
});
|
|
88
602
|
```
|
|
89
603
|
|
|
@@ -150,7 +664,7 @@ const bearerAuth: RequestAuthentication = {
|
|
|
150
664
|
inputProperty: 'headers.authorization',
|
|
151
665
|
outputProperty: 'auth.user',
|
|
152
666
|
handler: async (bearer: string) => {
|
|
153
|
-
//
|
|
667
|
+
// validateProperty header, return user
|
|
154
668
|
return {
|
|
155
669
|
name: 'John Doe',
|
|
156
670
|
id: 1,
|
|
@@ -213,7 +727,7 @@ const bearerAuth: RequestAuthentication = {
|
|
|
213
727
|
```typescript
|
|
214
728
|
interface ContextOptions {
|
|
215
729
|
allowUnknownFields?: boolean;
|
|
216
|
-
|
|
730
|
+
documentProperty?: {
|
|
217
731
|
description?: string;
|
|
218
732
|
operationId: string;
|
|
219
733
|
tags?: string[];
|
|
@@ -223,7 +737,7 @@ interface ContextOptions {
|
|
|
223
737
|
|
|
224
738
|
Setting "allowUnknownFields" to false protects your application from receiving unexpected properties in the request body, query, and files. It does not affect request.path, as path variables are defined at the routing level, nor does it affect request headers. Conversely, you can receive { name: 'John Doe', role: 'Admin' } when only expecting name.
|
|
225
739
|
|
|
226
|
-
The "
|
|
740
|
+
The "documentProperty" property is part of the Open API route definition and is optional.
|
|
227
741
|
|
|
228
742
|
3.2.3 Context.request
|
|
229
743
|
|
|
@@ -246,7 +760,7 @@ There's an example for request with path property only:
|
|
|
246
760
|
const request: ContextRequest = {
|
|
247
761
|
path: {
|
|
248
762
|
id: {
|
|
249
|
-
|
|
763
|
+
documentProperty: {
|
|
250
764
|
schema: {
|
|
251
765
|
type: 'string',
|
|
252
766
|
},
|
|
@@ -282,7 +796,7 @@ The execution context of validation.handler (and validation transform) is the re
|
|
|
282
796
|
const request: ContextRequest = {
|
|
283
797
|
body: {
|
|
284
798
|
role: {
|
|
285
|
-
|
|
799
|
+
documentProperty: {
|
|
286
800
|
schema: {
|
|
287
801
|
type: 'string',
|
|
288
802
|
},
|
|
@@ -315,7 +829,7 @@ is set to false, all non-described request properties (or non-described nested p
|
|
|
315
829
|
const request: ContextRequest = {
|
|
316
830
|
query: {
|
|
317
831
|
sortBy: {
|
|
318
|
-
|
|
832
|
+
documentProperty: {
|
|
319
833
|
schema: {
|
|
320
834
|
type: 'string',
|
|
321
835
|
},
|
|
@@ -337,7 +851,7 @@ const request: ContextRequest = {
|
|
|
337
851
|
},
|
|
338
852
|
},
|
|
339
853
|
sortOrder: {
|
|
340
|
-
|
|
854
|
+
documentProperty: {
|
|
341
855
|
schema: {
|
|
342
856
|
type: 'string',
|
|
343
857
|
},
|
|
@@ -514,4 +1028,4 @@ app.start(() => console.log('Your awesome application has been successfully laun
|
|
|
514
1028
|
app.stop(() => console.log('Your awesome application has been successfully launched'));
|
|
515
1029
|
```
|
|
516
1030
|
|
|
517
|
-
Don't forget to check swagger at the defined above options.
|
|
1031
|
+
Don't forget to check swagger at the defined above options.documentProperty.route
|
|
@@ -3,6 +3,7 @@ import { Server } from 'http';
|
|
|
3
3
|
import { AladoServerOptions } from '../options';
|
|
4
4
|
import { Context, Response } from '../dto';
|
|
5
5
|
export declare class AladoServer {
|
|
6
|
+
private readonly appId;
|
|
6
7
|
private readonly router;
|
|
7
8
|
private readonly server;
|
|
8
9
|
private readonly openApiDocObject;
|
|
@@ -6,6 +6,7 @@ const _router_1 = require("../router");
|
|
|
6
6
|
const _factory_1 = require("../factory");
|
|
7
7
|
const _helper_1 = require("../helpers");
|
|
8
8
|
class AladoServer {
|
|
9
|
+
appId;
|
|
9
10
|
router;
|
|
10
11
|
server;
|
|
11
12
|
openApiDocObject;
|
|
@@ -15,6 +16,7 @@ class AladoServer {
|
|
|
15
16
|
logger;
|
|
16
17
|
constructor(options) {
|
|
17
18
|
(0, _helper_1.validateAladoOptions)(options);
|
|
19
|
+
this.appId = options.appId || _const_1.DEFAULT_ID;
|
|
18
20
|
if (options.openApiDoc?.route) {
|
|
19
21
|
options.openApiDoc.route = `${(0, _helper_1.clearRoutePath)(options.openApiDoc.route)}`;
|
|
20
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alado-server.js","sourceRoot":"","sources":["../../src/alado-server/alado-server.ts"],"names":[],"mappings":";;;AAEA,
|
|
1
|
+
{"version":3,"file":"alado-server.js","sourceRoot":"","sources":["../../src/alado-server/alado-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_ID: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-id.js","sourceRoot":"","sources":["../../src/constants/default-id.ts"],"names":[],"mappings":";;;AAAa,QAAA,UAAU,GAAW,YAAY,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -20,4 +20,5 @@ __exportStar(require("./http-method"), exports);
|
|
|
20
20
|
__exportStar(require("./http-server"), exports);
|
|
21
21
|
__exportStar(require("./http-status"), exports);
|
|
22
22
|
__exportStar(require("./reg-exp"), exports);
|
|
23
|
+
__exportStar(require("./default-id"), exports);
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,uDAAqC;AACrC,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,4CAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,uDAAqC;AACrC,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,4CAA0B;AAC1B,+CAA6B"}
|