@webtypen/webframez-core 0.3.28 → 0.3.30
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 +345 -130
- package/dist/Router/Response.js +1 -1
- package/dist/Router/Route.d.ts +15 -12
- package/dist/Router/Route.js +30 -28
- package/package.json +1 -1
- package/src/Router/Response.ts +1 -1
- package/src/Router/Route.ts +52 -64
package/README.md
CHANGED
|
@@ -1,207 +1,422 @@
|
|
|
1
|
-
# webtypen
|
|
1
|
+
# @webtypen/webframez-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript-first backend framework core for Node.js.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This README reflects the current API in this repository and focuses on:
|
|
6
|
+
- Routing
|
|
7
|
+
- Datatables
|
|
8
|
+
- DataBuilder
|
|
9
|
+
- Console Commands
|
|
10
|
+
- Queue and Jobs
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
## Requirements
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
- Node.js `>= 20` (recommended)
|
|
15
|
+
- TypeScript for development
|
|
10
16
|
|
|
11
|
-
##
|
|
17
|
+
## Installation
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm i @webtypen/webframez-core
|
|
21
|
+
```
|
|
14
22
|
|
|
15
|
-
|
|
23
|
+
## Basic Web Setup
|
|
16
24
|
|
|
17
25
|
```ts
|
|
18
|
-
Route
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
import { BaseKernelWeb, Request, Response, Route, WebApplication } from "@webtypen/webframez-core";
|
|
27
|
+
|
|
28
|
+
class Kernel extends BaseKernelWeb {
|
|
29
|
+
static controller = {
|
|
30
|
+
TestController: class {
|
|
31
|
+
async index(req: Request, res: Response) {
|
|
32
|
+
return res.send({ status: "ok" });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
static middleware = {
|
|
38
|
+
auth: async (next: Function, reject: Function, req: Request, res: Response) => {
|
|
39
|
+
const isAllowed = true;
|
|
40
|
+
if (!isAllowed) {
|
|
41
|
+
return reject(new Error("Unauthorized"));
|
|
42
|
+
}
|
|
43
|
+
next(true);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const app = new WebApplication();
|
|
49
|
+
app.boot({
|
|
50
|
+
kernel: Kernel,
|
|
51
|
+
port: 3000,
|
|
52
|
+
basename: null,
|
|
53
|
+
routesFunction: () => {
|
|
54
|
+
Route.get("/", "TestController@index");
|
|
55
|
+
}
|
|
56
|
+
});
|
|
23
57
|
```
|
|
24
58
|
|
|
25
|
-
|
|
59
|
+
`WebApplication.boot(...)` supports:
|
|
60
|
+
- `kernel`
|
|
61
|
+
- `port`
|
|
62
|
+
- `basename`
|
|
63
|
+
- `routesFunction`
|
|
64
|
+
- `modules`
|
|
65
|
+
- `config`
|
|
66
|
+
- `datatables`
|
|
67
|
+
- `jobs`
|
|
68
|
+
- `mode`
|
|
69
|
+
- `onBoot`
|
|
26
70
|
|
|
27
|
-
|
|
71
|
+
## Routing
|
|
72
|
+
|
|
73
|
+
### Register Routes
|
|
28
74
|
|
|
29
75
|
```ts
|
|
30
|
-
|
|
31
|
-
Route.
|
|
76
|
+
Route.get("/", "HomeController@index");
|
|
77
|
+
Route.post("/login", "AuthController@login");
|
|
78
|
+
Route.put("/users/:id", "UserController@update");
|
|
79
|
+
Route.delete("/users/:id", "UserController@delete");
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
You can also register inline handlers:
|
|
32
83
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
84
|
+
```ts
|
|
85
|
+
Route.get("/health", (req: Request, res: Response) => {
|
|
86
|
+
return res.send({ status: "ok" });
|
|
87
|
+
});
|
|
36
88
|
```
|
|
37
89
|
|
|
38
|
-
###
|
|
90
|
+
### Path Parameters and Wildcards
|
|
39
91
|
|
|
40
|
-
|
|
92
|
+
Supported path patterns:
|
|
93
|
+
- Required parameter: `/:id`
|
|
94
|
+
- Optional parameter: `/:id?`
|
|
95
|
+
- Single wildcard: `/*`
|
|
96
|
+
- Catch-all wildcard: `/**`
|
|
41
97
|
|
|
42
|
-
|
|
98
|
+
Matched values are available in `req.params`.
|
|
43
99
|
|
|
44
|
-
|
|
45
|
-
- `abort`: Function that aborts the request when called. An HTTP status code can be specified in the first parameter and a request body (usually text or JSON) in the second.
|
|
46
|
-
- `req`: The Request-Object
|
|
47
|
-
- `res`: The Response-Object
|
|
100
|
+
### Route Groups
|
|
48
101
|
|
|
49
|
-
|
|
102
|
+
```ts
|
|
103
|
+
Route.group({ prefix: "/admin", middleware: ["auth"] }, () => {
|
|
104
|
+
Route.get("/dashboard", "AdminController@dashboard");
|
|
105
|
+
|
|
106
|
+
Route.group({ prefix: "/users" }, () => {
|
|
107
|
+
Route.get("/:id", "AdminUserController@details");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Route Middleware
|
|
113
|
+
|
|
114
|
+
Attach middleware by key via route options:
|
|
50
115
|
|
|
51
116
|
```ts
|
|
52
|
-
|
|
53
|
-
auth: async (next: any, abort: any, req: Request, res: Response) => {
|
|
54
|
-
console.log("auth-middleware");
|
|
55
|
-
next();
|
|
56
|
-
},
|
|
57
|
-
};
|
|
117
|
+
Route.get("/me", "AccountController@me", { middleware: ["auth"] });
|
|
58
118
|
```
|
|
59
119
|
|
|
60
|
-
|
|
120
|
+
Middleware signature:
|
|
61
121
|
|
|
62
|
-
|
|
122
|
+
```ts
|
|
123
|
+
(next, reject, req, res) => {
|
|
124
|
+
// allow:
|
|
125
|
+
next(true);
|
|
63
126
|
|
|
64
|
-
|
|
127
|
+
// abort with error:
|
|
128
|
+
// reject(new Error("Forbidden"));
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Extend the Route Facade
|
|
133
|
+
|
|
134
|
+
You can add custom route registration helpers:
|
|
65
135
|
|
|
66
136
|
```ts
|
|
67
|
-
Route.
|
|
137
|
+
Route.extend("jsonGet", (route) => {
|
|
138
|
+
return (path: string, component: any, options?: any) => {
|
|
139
|
+
route.get(path, async (req: Request, res: Response) => {
|
|
140
|
+
res.header("Content-Type", "application/json");
|
|
141
|
+
return component(req, res);
|
|
142
|
+
}, options);
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
(Route as any).jsonGet("/x", (req: Request, res: Response) => res.send({ ok: true }));
|
|
68
147
|
```
|
|
69
148
|
|
|
70
|
-
|
|
149
|
+
## Request and Response
|
|
150
|
+
|
|
151
|
+
### Request
|
|
71
152
|
|
|
72
|
-
|
|
153
|
+
`Request` includes:
|
|
154
|
+
- `method`, `url`, `headers`, `rawHeaders`
|
|
155
|
+
- `body`, `bodyPlain`
|
|
156
|
+
- `query`, `queryRaw`
|
|
157
|
+
- `params`
|
|
158
|
+
- `files`
|
|
159
|
+
- `message` (native `IncomingMessage`)
|
|
73
160
|
|
|
74
|
-
|
|
161
|
+
### Response
|
|
162
|
+
|
|
163
|
+
Common helpers:
|
|
75
164
|
|
|
76
165
|
```ts
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}});
|
|
166
|
+
res.status(201);
|
|
167
|
+
res.header("X-Test", "1");
|
|
168
|
+
res.send({ status: "success" });
|
|
81
169
|
```
|
|
82
170
|
|
|
83
|
-
|
|
171
|
+
Also available:
|
|
172
|
+
- `sendCsv(...)`
|
|
173
|
+
- `download(filepath, options?)`
|
|
174
|
+
- `stream(req, filepath, filename, mimeType)`
|
|
175
|
+
- `registerEvent("after", fn)`
|
|
176
|
+
|
|
177
|
+
## Datatables
|
|
178
|
+
|
|
179
|
+
Use `Datatable` + `DatatableRegistry` + `DatatableController`.
|
|
180
|
+
|
|
181
|
+
### Define a Datatable
|
|
84
182
|
|
|
85
183
|
```ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
184
|
+
import { Datatable, Request } from "@webtypen/webframez-core";
|
|
185
|
+
|
|
186
|
+
export class UsersTable extends Datatable {
|
|
187
|
+
collection = "users";
|
|
188
|
+
perPage = 25;
|
|
89
189
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
190
|
+
columns = {
|
|
191
|
+
name: { label: "Name" },
|
|
192
|
+
email: { label: "E-Mail" }
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
filter = {
|
|
196
|
+
name: { type: "text", mapping: "name" }
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
aggregation = async (req: Request) => {
|
|
200
|
+
return [{ $sort: { created_at: -1 } }];
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Register Datatables
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
app.boot({
|
|
209
|
+
// ...
|
|
210
|
+
datatables: {
|
|
211
|
+
users: UsersTable
|
|
212
|
+
}
|
|
213
|
+
});
|
|
93
214
|
```
|
|
94
215
|
|
|
95
|
-
|
|
216
|
+
### Datatable Endpoints
|
|
96
217
|
|
|
97
|
-
|
|
218
|
+
Use `DatatableController` in your routes:
|
|
98
219
|
|
|
99
220
|
```ts
|
|
100
|
-
|
|
101
|
-
Route.get("/", "TestController@test"); // Path: /test/
|
|
102
|
-
Route.get("/test2", "TestController@test"); // Path: /test2/
|
|
221
|
+
import { DatatableController, Route } from "@webtypen/webframez-core";
|
|
103
222
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
});
|
|
223
|
+
Route.post("/api/datatable", "DatatableController@restApi");
|
|
224
|
+
Route.post("/api/datatable/export", "DatatableController@tableExport");
|
|
108
225
|
```
|
|
109
226
|
|
|
110
|
-
|
|
227
|
+
`restApi` supports:
|
|
228
|
+
- init requests (`init_request`)
|
|
229
|
+
- paginated data
|
|
230
|
+
- selectable functions (`apiFunction`)
|
|
111
231
|
|
|
112
|
-
|
|
232
|
+
`tableExport` uses your table `exports` definition.
|
|
113
233
|
|
|
114
|
-
|
|
234
|
+
## DataBuilder
|
|
115
235
|
|
|
116
|
-
|
|
236
|
+
Use `DataBuilder` + `DataBuilderController` for schema-driven CRUD flows.
|
|
117
237
|
|
|
118
|
-
|
|
238
|
+
### Define and Register Types
|
|
119
239
|
|
|
120
|
-
|
|
240
|
+
```ts
|
|
241
|
+
import { DataBuilder } from "@webtypen/webframez-core";
|
|
242
|
+
|
|
243
|
+
const builder = new DataBuilder();
|
|
244
|
+
|
|
245
|
+
builder.registerType({
|
|
246
|
+
key: "user",
|
|
247
|
+
singular: "User",
|
|
248
|
+
plural: "Users",
|
|
249
|
+
schema: {
|
|
250
|
+
version: "1.0.0",
|
|
251
|
+
collection: "users",
|
|
252
|
+
fields: {
|
|
253
|
+
email: { type: "text", required: true, unique: { match: {} } },
|
|
254
|
+
age: { type: "integer" }
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
You can also use:
|
|
261
|
+
- `registerModelType(...)`
|
|
262
|
+
- `registerFieldType(...)`
|
|
121
263
|
|
|
122
|
-
|
|
264
|
+
### Expose the REST API
|
|
123
265
|
|
|
124
266
|
```ts
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
267
|
+
import { DataBuilderController, Route } from "@webtypen/webframez-core";
|
|
268
|
+
|
|
269
|
+
class MyDataBuilderController extends DataBuilderController {
|
|
270
|
+
constructor() {
|
|
271
|
+
super(builder);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Register controller in kernel, then:
|
|
276
|
+
Route.post("/api/builder", "MyDataBuilderController@restApi");
|
|
134
277
|
```
|
|
135
278
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* @param foreignKey
|
|
163
|
-
* @param localKey (optional)
|
|
164
|
-
* @param queryBuilderFunction (optional) customize the query
|
|
165
|
-
**/
|
|
166
|
-
@hasMany(() => Session, "_user")
|
|
167
|
-
sessions!: () => Session[];
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* @param CustomerGroups Dependency Model
|
|
171
|
-
* @param foreignKey
|
|
172
|
-
* @param localKey (optional)
|
|
173
|
-
* @param queryBuilderFunction (optional) customize the query
|
|
174
|
-
**/
|
|
175
|
-
@hasManyArray(() => CustomerGroups, "_groups")
|
|
176
|
-
groups!: () => CustomerGroups[];
|
|
279
|
+
`__builder_rest_api` actions:
|
|
280
|
+
- `type`
|
|
281
|
+
- `details`
|
|
282
|
+
- `details-newdata`
|
|
283
|
+
- `save`
|
|
284
|
+
- `delete`
|
|
285
|
+
- `api-autocomplete`
|
|
286
|
+
|
|
287
|
+
## Console Commands
|
|
288
|
+
|
|
289
|
+
Use `ConsoleApplication` with `BaseKernelConsole`.
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
import { BaseKernelConsole, ConsoleApplication, ConsoleCommand } from "@webtypen/webframez-core";
|
|
293
|
+
|
|
294
|
+
class HelloCommand extends ConsoleCommand {
|
|
295
|
+
static signature = "hello";
|
|
296
|
+
static description = "Print a greeting";
|
|
297
|
+
|
|
298
|
+
async handle() {
|
|
299
|
+
this.success("Hello world");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
class KernelConsole extends BaseKernelConsole {
|
|
304
|
+
static commands = [HelloCommand];
|
|
177
305
|
}
|
|
306
|
+
|
|
307
|
+
const app = new ConsoleApplication();
|
|
308
|
+
app.boot({
|
|
309
|
+
kernel: KernelConsole,
|
|
310
|
+
config: {}
|
|
311
|
+
});
|
|
178
312
|
```
|
|
179
313
|
|
|
180
|
-
|
|
314
|
+
`ConsoleCommand` helpers include:
|
|
315
|
+
- `getArguments()`, `getOptions()`, `getOption(...)`
|
|
316
|
+
- `ask(...)`
|
|
317
|
+
- `write`, `writeln`, `info`, `warning`, `success`, `error`
|
|
318
|
+
- progress helpers (`progress`, `progressIncrement`, `progressFinish`)
|
|
319
|
+
|
|
320
|
+
## Queue and Jobs
|
|
321
|
+
|
|
322
|
+
Queue workers run through console commands and use `queue_jobs` storage.
|
|
323
|
+
|
|
324
|
+
### Create a Job
|
|
181
325
|
|
|
182
326
|
```ts
|
|
183
|
-
import {
|
|
327
|
+
import { BaseQueueJob } from "@webtypen/webframez-core";
|
|
328
|
+
|
|
329
|
+
export class SendMailJob extends BaseQueueJob {
|
|
330
|
+
async handle(job: any) {
|
|
331
|
+
this.log("Sending mail", job.payload);
|
|
332
|
+
// do work...
|
|
333
|
+
|
|
334
|
+
// optional delayed re-run:
|
|
335
|
+
// return this.executeAgain(5, "minutes");
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
184
339
|
|
|
185
|
-
|
|
186
|
-
|
|
340
|
+
Create a new queue entry:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
await SendMailJob.create({
|
|
344
|
+
payload: { userId: "..." },
|
|
345
|
+
priority: 5,
|
|
346
|
+
worker: null
|
|
347
|
+
});
|
|
187
348
|
```
|
|
188
349
|
|
|
189
|
-
|
|
350
|
+
### Register Jobs
|
|
190
351
|
|
|
191
352
|
```ts
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
353
|
+
app.boot({
|
|
354
|
+
// ConsoleApplication or WebApplication
|
|
355
|
+
jobs: [SendMailJob]
|
|
356
|
+
});
|
|
195
357
|
```
|
|
196
358
|
|
|
197
|
-
|
|
359
|
+
### Queue Config
|
|
360
|
+
|
|
361
|
+
Configure workers in `config.queue`:
|
|
198
362
|
|
|
199
363
|
```ts
|
|
200
|
-
|
|
364
|
+
export default {
|
|
365
|
+
workers: {
|
|
366
|
+
default: {
|
|
367
|
+
is_active: true,
|
|
368
|
+
jobclasses: ["SendMailJob"],
|
|
369
|
+
automation: [
|
|
370
|
+
{
|
|
371
|
+
jobclass: "SendMailJob",
|
|
372
|
+
executions: [
|
|
373
|
+
["every_x_mins", 15],
|
|
374
|
+
["daily", "08:00"],
|
|
375
|
+
["every_hour", 5],
|
|
376
|
+
["mondays", "09:30"]
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
201
383
|
```
|
|
202
384
|
|
|
203
|
-
|
|
385
|
+
### Built-in Queue Commands
|
|
386
|
+
|
|
387
|
+
- `queue:start`
|
|
388
|
+
- `queue:status`
|
|
389
|
+
- `queue:stop`
|
|
390
|
+
- `queue:log`
|
|
391
|
+
- `queue:worker`
|
|
392
|
+
- `queue:worker:autorestart`
|
|
393
|
+
|
|
394
|
+
Additional built-in command:
|
|
395
|
+
- `build`
|
|
396
|
+
|
|
397
|
+
## Modules
|
|
398
|
+
|
|
399
|
+
You can load module providers via `modules` in `WebApplication.boot(...)`.
|
|
400
|
+
|
|
401
|
+
A module provider can:
|
|
402
|
+
- register controllers/middleware
|
|
403
|
+
- define `boot()`
|
|
404
|
+
- define `routes()`
|
|
405
|
+
|
|
406
|
+
## Lambda Mode
|
|
407
|
+
|
|
408
|
+
`LambdaApplication` uses the same router in AWS Lambda mode:
|
|
204
409
|
|
|
205
410
|
```ts
|
|
206
|
-
|
|
411
|
+
import { LambdaApplication } from "@webtypen/webframez-core";
|
|
412
|
+
|
|
413
|
+
const app = new LambdaApplication();
|
|
414
|
+
export const handler = (event: any, context: any) => {
|
|
415
|
+
return app.boot(event, context, {
|
|
416
|
+
kernel: Kernel,
|
|
417
|
+
routesFunction: () => {
|
|
418
|
+
Route.get("/status", (req, res) => res.send({ ok: true }));
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
207
422
|
```
|
package/dist/Router/Response.js
CHANGED
|
@@ -158,7 +158,7 @@ class Response {
|
|
|
158
158
|
this.header("Content-Disposition", `attachment; filename="${filename}"`);
|
|
159
159
|
}
|
|
160
160
|
// @ts-ignore
|
|
161
|
-
var readStream = fs_1.default.createReadStream(
|
|
161
|
+
var readStream = fs_1.default.createReadStream(filepath, { start: start, end: end });
|
|
162
162
|
readStream.on("error", (streamError) => {
|
|
163
163
|
console.error("WebframezStreamError:", streamError);
|
|
164
164
|
});
|
package/dist/Router/Route.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
type RouteRegistrationOptions = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
};
|
|
4
|
+
type RouteExtensionFactory = (route: RouteFacade) => (...args: any[]) => any;
|
|
1
5
|
export declare class RouteFacade {
|
|
2
6
|
tempGroupPrefix: string | null;
|
|
3
7
|
tempGroupMiddleware: string[] | null;
|
|
8
|
+
private registerWithGroupContext;
|
|
9
|
+
/**
|
|
10
|
+
* Register a custom route-method on the Route facade.
|
|
11
|
+
* Allows optional packages to add framework-specific route helpers.
|
|
12
|
+
*/
|
|
13
|
+
extend(name: string, factory: RouteExtensionFactory): this;
|
|
4
14
|
/**
|
|
5
15
|
* Register a GET-Method
|
|
6
16
|
*
|
|
@@ -8,9 +18,7 @@ export declare class RouteFacade {
|
|
|
8
18
|
* @param component
|
|
9
19
|
* @param options
|
|
10
20
|
*/
|
|
11
|
-
get(path: string, component: any, options?:
|
|
12
|
-
[key: string]: any;
|
|
13
|
-
}): void;
|
|
21
|
+
get(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
14
22
|
/**
|
|
15
23
|
* Register a POST-Method
|
|
16
24
|
*
|
|
@@ -18,9 +26,7 @@ export declare class RouteFacade {
|
|
|
18
26
|
* @param component
|
|
19
27
|
* @param options
|
|
20
28
|
*/
|
|
21
|
-
post(path: string, component: any, options?:
|
|
22
|
-
[key: string]: any;
|
|
23
|
-
}): void;
|
|
29
|
+
post(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
24
30
|
/**
|
|
25
31
|
* Register a PUT-Method
|
|
26
32
|
*
|
|
@@ -28,9 +34,7 @@ export declare class RouteFacade {
|
|
|
28
34
|
* @param component
|
|
29
35
|
* @param options
|
|
30
36
|
*/
|
|
31
|
-
put(path: string, component: any, options?:
|
|
32
|
-
[key: string]: any;
|
|
33
|
-
}): void;
|
|
37
|
+
put(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
34
38
|
/**
|
|
35
39
|
* Register a DELETE-Method
|
|
36
40
|
*
|
|
@@ -38,11 +42,10 @@ export declare class RouteFacade {
|
|
|
38
42
|
* @param component
|
|
39
43
|
* @param options
|
|
40
44
|
*/
|
|
41
|
-
delete(path: string, component: any, options?:
|
|
42
|
-
[key: string]: any;
|
|
43
|
-
}): void;
|
|
45
|
+
delete(path: string, component: any, options?: RouteRegistrationOptions): void;
|
|
44
46
|
group(config: {
|
|
45
47
|
[key: string]: any;
|
|
46
48
|
}, children: any): void;
|
|
47
49
|
}
|
|
48
50
|
export declare const Route: RouteFacade;
|
|
51
|
+
export {};
|
package/dist/Router/Route.js
CHANGED
|
@@ -6,6 +6,32 @@ class RouteFacade {
|
|
|
6
6
|
constructor() {
|
|
7
7
|
this.tempGroupPrefix = null;
|
|
8
8
|
this.tempGroupMiddleware = null;
|
|
9
|
+
this.registerWithGroupContext = (method, path, component, options) => {
|
|
10
|
+
Router_1.Router.register(method, (this.tempGroupPrefix ? this.tempGroupPrefix : "") + path, component, options || this.tempGroupMiddleware
|
|
11
|
+
? Object.assign(Object.assign({}, (options ? options : {})), { middleware: this.tempGroupMiddleware || (options && options.middleware)
|
|
12
|
+
? [
|
|
13
|
+
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
14
|
+
...(options && options.middleware ? options.middleware : []),
|
|
15
|
+
]
|
|
16
|
+
: null }) : {});
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a custom route-method on the Route facade.
|
|
21
|
+
* Allows optional packages to add framework-specific route helpers.
|
|
22
|
+
*/
|
|
23
|
+
extend(name, factory) {
|
|
24
|
+
if (!name || name.trim() === "") {
|
|
25
|
+
throw new Error("Route.extend requires a non-empty method name");
|
|
26
|
+
}
|
|
27
|
+
if (name in this && typeof this[name] === "function") {
|
|
28
|
+
throw new Error("Route method '" + name + "' already exists");
|
|
29
|
+
}
|
|
30
|
+
if (!factory || typeof factory !== "function") {
|
|
31
|
+
throw new Error("Route.extend requires a factory function");
|
|
32
|
+
}
|
|
33
|
+
this[name] = factory(this);
|
|
34
|
+
return this;
|
|
9
35
|
}
|
|
10
36
|
/**
|
|
11
37
|
* Register a GET-Method
|
|
@@ -15,13 +41,7 @@ class RouteFacade {
|
|
|
15
41
|
* @param options
|
|
16
42
|
*/
|
|
17
43
|
get(path, component, options) {
|
|
18
|
-
|
|
19
|
-
? Object.assign(Object.assign({}, (options ? options : {})), { middleware: this.tempGroupMiddleware || (options && options.middleware)
|
|
20
|
-
? [
|
|
21
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
22
|
-
...(options && options.middleware ? options.middleware : []),
|
|
23
|
-
]
|
|
24
|
-
: null }) : {});
|
|
44
|
+
this.registerWithGroupContext("GET", path, component, options);
|
|
25
45
|
}
|
|
26
46
|
/**
|
|
27
47
|
* Register a POST-Method
|
|
@@ -31,13 +51,7 @@ class RouteFacade {
|
|
|
31
51
|
* @param options
|
|
32
52
|
*/
|
|
33
53
|
post(path, component, options) {
|
|
34
|
-
|
|
35
|
-
? Object.assign(Object.assign({}, (options ? options : {})), { middleware: this.tempGroupMiddleware || (options && options.middleware)
|
|
36
|
-
? [
|
|
37
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
38
|
-
...(options && options.middleware ? options.middleware : []),
|
|
39
|
-
]
|
|
40
|
-
: null }) : {});
|
|
54
|
+
this.registerWithGroupContext("POST", path, component, options);
|
|
41
55
|
}
|
|
42
56
|
/**
|
|
43
57
|
* Register a PUT-Method
|
|
@@ -47,13 +61,7 @@ class RouteFacade {
|
|
|
47
61
|
* @param options
|
|
48
62
|
*/
|
|
49
63
|
put(path, component, options) {
|
|
50
|
-
|
|
51
|
-
? Object.assign(Object.assign({}, (options ? options : {})), { middleware: this.tempGroupMiddleware || (options && options.middleware)
|
|
52
|
-
? [
|
|
53
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
54
|
-
...(options && options.middleware ? options.middleware : []),
|
|
55
|
-
]
|
|
56
|
-
: null }) : {});
|
|
64
|
+
this.registerWithGroupContext("PUT", path, component, options);
|
|
57
65
|
}
|
|
58
66
|
/**
|
|
59
67
|
* Register a DELETE-Method
|
|
@@ -63,13 +71,7 @@ class RouteFacade {
|
|
|
63
71
|
* @param options
|
|
64
72
|
*/
|
|
65
73
|
delete(path, component, options) {
|
|
66
|
-
|
|
67
|
-
? Object.assign(Object.assign({}, (options ? options : {})), { middleware: this.tempGroupMiddleware || (options && options.middleware)
|
|
68
|
-
? [
|
|
69
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
70
|
-
...(options && options.middleware ? options.middleware : []),
|
|
71
|
-
]
|
|
72
|
-
: null }) : {});
|
|
74
|
+
this.registerWithGroupContext("DELETE", path, component, options);
|
|
73
75
|
}
|
|
74
76
|
group(config, children) {
|
|
75
77
|
// Handle group prefix
|
package/package.json
CHANGED
package/src/Router/Response.ts
CHANGED
|
@@ -166,7 +166,7 @@ export class Response {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// @ts-ignore
|
|
169
|
-
var readStream = fs.createReadStream(
|
|
169
|
+
var readStream = fs.createReadStream(filepath, { start: start, end: end });
|
|
170
170
|
|
|
171
171
|
readStream.on("error", (streamError) => {
|
|
172
172
|
console.error("WebframezStreamError:", streamError);
|
package/src/Router/Route.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { Router } from "./Router";
|
|
2
2
|
|
|
3
|
+
type RouteRegistrationOptions = { [key: string]: any };
|
|
4
|
+
type RouteRegistrationHandler = (
|
|
5
|
+
method: string,
|
|
6
|
+
path: string,
|
|
7
|
+
component: any,
|
|
8
|
+
options?: RouteRegistrationOptions
|
|
9
|
+
) => void;
|
|
10
|
+
|
|
11
|
+
type RouteExtensionFactory = (route: RouteFacade) => (...args: any[]) => any;
|
|
12
|
+
|
|
3
13
|
export class RouteFacade {
|
|
4
14
|
tempGroupPrefix: string | null = null;
|
|
5
15
|
tempGroupMiddleware: string[] | null = null;
|
|
6
16
|
|
|
7
|
-
|
|
8
|
-
* Register a GET-Method
|
|
9
|
-
*
|
|
10
|
-
* @param path
|
|
11
|
-
* @param component
|
|
12
|
-
* @param options
|
|
13
|
-
*/
|
|
14
|
-
get(path: string, component: any, options?: { [key: string]: any }) {
|
|
17
|
+
private registerWithGroupContext: RouteRegistrationHandler = (method, path, component, options) => {
|
|
15
18
|
Router.register(
|
|
16
|
-
|
|
19
|
+
method,
|
|
17
20
|
(this.tempGroupPrefix ? this.tempGroupPrefix : "") + path,
|
|
18
21
|
component,
|
|
19
22
|
options || this.tempGroupMiddleware
|
|
@@ -29,6 +32,38 @@ export class RouteFacade {
|
|
|
29
32
|
}
|
|
30
33
|
: {}
|
|
31
34
|
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Register a custom route-method on the Route facade.
|
|
39
|
+
* Allows optional packages to add framework-specific route helpers.
|
|
40
|
+
*/
|
|
41
|
+
extend(name: string, factory: RouteExtensionFactory) {
|
|
42
|
+
if (!name || name.trim() === "") {
|
|
43
|
+
throw new Error("Route.extend requires a non-empty method name");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (name in this && typeof (this as any)[name] === "function") {
|
|
47
|
+
throw new Error("Route method '" + name + "' already exists");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!factory || typeof factory !== "function") {
|
|
51
|
+
throw new Error("Route.extend requires a factory function");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
(this as any)[name] = factory(this);
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Register a GET-Method
|
|
60
|
+
*
|
|
61
|
+
* @param path
|
|
62
|
+
* @param component
|
|
63
|
+
* @param options
|
|
64
|
+
*/
|
|
65
|
+
get(path: string, component: any, options?: RouteRegistrationOptions) {
|
|
66
|
+
this.registerWithGroupContext("GET", path, component, options);
|
|
32
67
|
}
|
|
33
68
|
|
|
34
69
|
/**
|
|
@@ -38,24 +73,8 @@ export class RouteFacade {
|
|
|
38
73
|
* @param component
|
|
39
74
|
* @param options
|
|
40
75
|
*/
|
|
41
|
-
post(path: string, component: any, options?:
|
|
42
|
-
|
|
43
|
-
"POST",
|
|
44
|
-
(this.tempGroupPrefix ? this.tempGroupPrefix : "") + path,
|
|
45
|
-
component,
|
|
46
|
-
options || this.tempGroupMiddleware
|
|
47
|
-
? {
|
|
48
|
-
...(options ? options : {}),
|
|
49
|
-
middleware:
|
|
50
|
-
this.tempGroupMiddleware || (options && options.middleware)
|
|
51
|
-
? [
|
|
52
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
53
|
-
...(options && options.middleware ? options.middleware : []),
|
|
54
|
-
]
|
|
55
|
-
: null,
|
|
56
|
-
}
|
|
57
|
-
: {}
|
|
58
|
-
);
|
|
76
|
+
post(path: string, component: any, options?: RouteRegistrationOptions) {
|
|
77
|
+
this.registerWithGroupContext("POST", path, component, options);
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
/**
|
|
@@ -65,24 +84,8 @@ export class RouteFacade {
|
|
|
65
84
|
* @param component
|
|
66
85
|
* @param options
|
|
67
86
|
*/
|
|
68
|
-
put(path: string, component: any, options?:
|
|
69
|
-
|
|
70
|
-
"PUT",
|
|
71
|
-
(this.tempGroupPrefix ? this.tempGroupPrefix : "") + path,
|
|
72
|
-
component,
|
|
73
|
-
options || this.tempGroupMiddleware
|
|
74
|
-
? {
|
|
75
|
-
...(options ? options : {}),
|
|
76
|
-
middleware:
|
|
77
|
-
this.tempGroupMiddleware || (options && options.middleware)
|
|
78
|
-
? [
|
|
79
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
80
|
-
...(options && options.middleware ? options.middleware : []),
|
|
81
|
-
]
|
|
82
|
-
: null,
|
|
83
|
-
}
|
|
84
|
-
: {}
|
|
85
|
-
);
|
|
87
|
+
put(path: string, component: any, options?: RouteRegistrationOptions) {
|
|
88
|
+
this.registerWithGroupContext("PUT", path, component, options);
|
|
86
89
|
}
|
|
87
90
|
|
|
88
91
|
/**
|
|
@@ -92,30 +95,15 @@ export class RouteFacade {
|
|
|
92
95
|
* @param component
|
|
93
96
|
* @param options
|
|
94
97
|
*/
|
|
95
|
-
delete(path: string, component: any, options?:
|
|
96
|
-
|
|
97
|
-
"DELETE",
|
|
98
|
-
(this.tempGroupPrefix ? this.tempGroupPrefix : "") + path,
|
|
99
|
-
component,
|
|
100
|
-
options || this.tempGroupMiddleware
|
|
101
|
-
? {
|
|
102
|
-
...(options ? options : {}),
|
|
103
|
-
middleware:
|
|
104
|
-
this.tempGroupMiddleware || (options && options.middleware)
|
|
105
|
-
? [
|
|
106
|
-
...(this.tempGroupMiddleware ? this.tempGroupMiddleware : []),
|
|
107
|
-
...(options && options.middleware ? options.middleware : []),
|
|
108
|
-
]
|
|
109
|
-
: null,
|
|
110
|
-
}
|
|
111
|
-
: {}
|
|
112
|
-
);
|
|
98
|
+
delete(path: string, component: any, options?: RouteRegistrationOptions) {
|
|
99
|
+
this.registerWithGroupContext("DELETE", path, component, options);
|
|
113
100
|
}
|
|
114
101
|
|
|
115
102
|
group(config: { [key: string]: any }, children: any) {
|
|
116
103
|
// Handle group prefix
|
|
117
104
|
const tempGroupPrefixBefore = this.tempGroupPrefix ? this.tempGroupPrefix + "" : null;
|
|
118
|
-
const tempGroupMiddlewareBefore =
|
|
105
|
+
const tempGroupMiddlewareBefore =
|
|
106
|
+
this.tempGroupMiddleware && this.tempGroupMiddleware.length > 0 ? this.tempGroupMiddleware : null;
|
|
119
107
|
if (config && config.prefix && config.prefix.trim() !== "") {
|
|
120
108
|
this.tempGroupPrefix = (this.tempGroupPrefix ? this.tempGroupPrefix : "") + config.prefix;
|
|
121
109
|
}
|