5htp-core 0.5.0-9 → 0.5.1-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.1-1",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// Node
|
|
13
13
|
// Npm
|
|
14
14
|
import type express from 'express';
|
|
15
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
15
16
|
import { v4 as uuid } from 'uuid';
|
|
16
17
|
import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
|
|
17
18
|
|
|
@@ -265,7 +266,31 @@ export default class ServerRouter<
|
|
|
265
266
|
public post = (...args: TApiRegisterArgs<this>) => this.registerApi('POST', ...args);
|
|
266
267
|
public put = (...args: TApiRegisterArgs<this>) => this.registerApi('PUT', ...args);
|
|
267
268
|
public patch = (...args: TApiRegisterArgs<this>) => this.registerApi('PATCH', ...args);
|
|
268
|
-
public delete = (...args: TApiRegisterArgs<this>) => this.registerApi('DELETE', ...args)
|
|
269
|
+
public delete = (...args: TApiRegisterArgs<this>) => this.registerApi('DELETE', ...args);
|
|
270
|
+
|
|
271
|
+
public express(
|
|
272
|
+
middleware: (
|
|
273
|
+
req: Request,
|
|
274
|
+
res: Response,
|
|
275
|
+
next: NextFunction,
|
|
276
|
+
requestContext: TRouterContext
|
|
277
|
+
) => void
|
|
278
|
+
) {
|
|
279
|
+
return (context: TRouterContext) => new Promise((resolve) => {
|
|
280
|
+
|
|
281
|
+
context.request.res.on('finish', function() {
|
|
282
|
+
//console.log('the response has been sent', request.res.statusCode);
|
|
283
|
+
resolve(true);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
middleware(
|
|
287
|
+
context.request.req,
|
|
288
|
+
context.request.res,
|
|
289
|
+
() => { resolve(true); },
|
|
290
|
+
context
|
|
291
|
+
)
|
|
292
|
+
})
|
|
293
|
+
}
|
|
269
294
|
|
|
270
295
|
protected registerApi(method: TRouteHttpMethod, ...args: TApiRegisterArgs<this>): this {
|
|
271
296
|
|
|
@@ -432,12 +457,16 @@ declare type Routes = {
|
|
|
432
457
|
response = await this.handleError(e, request);
|
|
433
458
|
}
|
|
434
459
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
460
|
+
if (!res.headersSent) {
|
|
461
|
+
// Status
|
|
462
|
+
res.status(response.statusCode);
|
|
463
|
+
// Headers
|
|
464
|
+
res.header(response.headers);
|
|
465
|
+
// Data
|
|
466
|
+
res.send(response.data);
|
|
467
|
+
} else if (response.data !== 'true') {
|
|
468
|
+
throw new Error("Can't return data from the controller since response has already been sent via express.");
|
|
469
|
+
}
|
|
441
470
|
|
|
442
471
|
});
|
|
443
472
|
}
|
|
@@ -490,7 +519,6 @@ declare type Routes = {
|
|
|
490
519
|
|
|
491
520
|
// Run on resolution hooks. Ex: authentication check
|
|
492
521
|
await this.runHook('resolved', route);
|
|
493
|
-
|
|
494
522
|
const timeEndResolving = Date.now();
|
|
495
523
|
|
|
496
524
|
// Create response
|
|
@@ -82,6 +82,7 @@ export default class ServerResponse<
|
|
|
82
82
|
public headers: {[cle: string]: string} = {}
|
|
83
83
|
public cookie: express.Response["cookie"];
|
|
84
84
|
public clearCookie: express.Response["clearCookie"];
|
|
85
|
+
public canonicalUrl: URL;
|
|
85
86
|
|
|
86
87
|
// If data was provided by at lead one controller
|
|
87
88
|
public wasProvided = false;
|
|
@@ -95,12 +96,18 @@ export default class ServerResponse<
|
|
|
95
96
|
|
|
96
97
|
this.router = request.router;
|
|
97
98
|
this.app = this.router.app;
|
|
99
|
+
|
|
100
|
+
this.canonicalUrl = new URL(request.url);
|
|
101
|
+
this.canonicalUrl.search = '';
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
public async runController( route: TAnyRoute, additionnalData: {} = {} ) {
|
|
101
105
|
|
|
102
106
|
this.route = route;
|
|
103
107
|
|
|
108
|
+
// Update canonical url
|
|
109
|
+
this.updateCanonicalUrl(route);
|
|
110
|
+
|
|
104
111
|
// Create response context for controllers
|
|
105
112
|
const context = await this.createContext(route);
|
|
106
113
|
|
|
@@ -140,6 +147,18 @@ export default class ServerResponse<
|
|
|
140
147
|
this.router.cache[ chunkId ] = this.data;
|
|
141
148
|
}
|
|
142
149
|
|
|
150
|
+
private updateCanonicalUrl( route: TAnyRoute ) {
|
|
151
|
+
|
|
152
|
+
if (!route.options.canonicalParams)
|
|
153
|
+
return;
|
|
154
|
+
|
|
155
|
+
for (const key of route.options.canonicalParams) {
|
|
156
|
+
const paramValue = this.request.data[ key ];
|
|
157
|
+
if (paramValue !== undefined)
|
|
158
|
+
this.canonicalUrl.searchParams.set(key, paramValue);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
143
162
|
/*----------------------------------
|
|
144
163
|
- INTERNAL
|
|
145
164
|
----------------------------------*/
|
|
@@ -57,9 +57,6 @@ export default class DocumentRenderer<TRouter extends Router> {
|
|
|
57
57
|
|
|
58
58
|
public async page( html: string, page: Page, response: ServerResponse<TRouter> ) {
|
|
59
59
|
|
|
60
|
-
// TODO: can be customized via page / route config
|
|
61
|
-
const canonicalUrl = response.request.url;
|
|
62
|
-
|
|
63
60
|
let attrsBody = {
|
|
64
61
|
className: [...page.bodyClass].join(' '),
|
|
65
62
|
};
|
|
@@ -94,7 +91,7 @@ export default class DocumentRenderer<TRouter extends Router> {
|
|
|
94
91
|
{/* Page */}
|
|
95
92
|
<title>{page.title}</title>
|
|
96
93
|
<meta content={page.description} name="description" />
|
|
97
|
-
<link rel="canonical" href={canonicalUrl} />
|
|
94
|
+
<link rel="canonical" href={response.canonicalUrl} />
|
|
98
95
|
|
|
99
96
|
{/* SEO, social medias, OG tags, ... */}
|
|
100
97
|
{page.head.map(({ $, ...attrs }) => (
|