5htp-core 0.6.0-97 → 0.6.0-99
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/common/router/index.ts
CHANGED
|
@@ -98,7 +98,10 @@ export type TRouteOptions = {
|
|
|
98
98
|
redirectLogged?: string, // Redirect to this route if auth: false and user is logged
|
|
99
99
|
|
|
100
100
|
// Rendering
|
|
101
|
-
static?:
|
|
101
|
+
static?: {
|
|
102
|
+
refresh?: string,
|
|
103
|
+
urls: string[]
|
|
104
|
+
},
|
|
102
105
|
canonicalParams?: string[], // For SEO + unique ID for static cache
|
|
103
106
|
layout?: false | string, // The nale of the layout
|
|
104
107
|
|
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.6.0-
|
|
4
|
+
"version": "0.6.0-99",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"regenerator-runtime": "^0.13.9",
|
|
77
77
|
"request": "^2.88.2",
|
|
78
78
|
"slugify": "^1.6.6",
|
|
79
|
+
"source-map-support": "^0.5.21",
|
|
79
80
|
"sql-formatter": "^4.0.2",
|
|
80
81
|
"stopword": "^3.1.1",
|
|
81
82
|
"tslog": "^4.9.1",
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
// Node
|
|
13
13
|
// Npm
|
|
14
|
+
import got from 'got';
|
|
15
|
+
import hInterval from 'human-interval';
|
|
14
16
|
import type express from 'express';
|
|
15
17
|
import type { Request, Response, NextFunction } from 'express';
|
|
16
18
|
import { v4 as uuid } from 'uuid';
|
|
@@ -137,7 +139,13 @@ export default class ServerRouter
|
|
|
137
139
|
public ssrRoutes: TSsrUnresolvedRoute[] = [];
|
|
138
140
|
|
|
139
141
|
// Cache (ex: for static pages)
|
|
140
|
-
public cache: {
|
|
142
|
+
public cache: {
|
|
143
|
+
[pageId: string]: {
|
|
144
|
+
rendered: any,
|
|
145
|
+
expire: number | undefined,
|
|
146
|
+
options: TRouteOptions["static"]
|
|
147
|
+
}
|
|
148
|
+
} = {}
|
|
141
149
|
|
|
142
150
|
/*----------------------------------
|
|
143
151
|
- SERVICE
|
|
@@ -157,6 +165,11 @@ export default class ServerRouter
|
|
|
157
165
|
|
|
158
166
|
public async ready() {
|
|
159
167
|
|
|
168
|
+
// Every hours
|
|
169
|
+
setInterval(() => {
|
|
170
|
+
this.refreshStaticPages();
|
|
171
|
+
}, 1000 * 60 * 60);
|
|
172
|
+
|
|
160
173
|
// Detect router services
|
|
161
174
|
for (const serviceName in this.config.plugins) {
|
|
162
175
|
this.app.register( this.config.plugins[serviceName] )
|
|
@@ -172,7 +185,6 @@ export default class ServerRouter
|
|
|
172
185
|
// Start HTTP server
|
|
173
186
|
await this.http.start();
|
|
174
187
|
|
|
175
|
-
|
|
176
188
|
// override
|
|
177
189
|
const originalLog = console.log;
|
|
178
190
|
console.log = (...args: any[]) => {
|
|
@@ -209,6 +221,65 @@ export default class ServerRouter
|
|
|
209
221
|
- ACTIONS
|
|
210
222
|
----------------------------------*/
|
|
211
223
|
|
|
224
|
+
private async renderStatic(
|
|
225
|
+
path: string,
|
|
226
|
+
options: TRouteOptions["static"],
|
|
227
|
+
rendered?: any
|
|
228
|
+
) {
|
|
229
|
+
|
|
230
|
+
// Wildcard: tell that the newly rendered pages should be cached
|
|
231
|
+
if (path === '*')
|
|
232
|
+
return;
|
|
233
|
+
|
|
234
|
+
if (!rendered) {
|
|
235
|
+
|
|
236
|
+
const fullUrl = this.url(path, {}, true);
|
|
237
|
+
console.log('[router] renderStatic', fullUrl);
|
|
238
|
+
|
|
239
|
+
const response = await got( fullUrl, {
|
|
240
|
+
method: 'GET',
|
|
241
|
+
headers: {
|
|
242
|
+
'Accept': 'text/html'
|
|
243
|
+
},
|
|
244
|
+
throwHttpErrors: false,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
if (response.statusCode !== 200) {
|
|
248
|
+
console.error('renderStatic', response.statusCode, response.body);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
rendered = response.body;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
this.cache[path] = {
|
|
256
|
+
rendered: rendered,
|
|
257
|
+
options: options,
|
|
258
|
+
expire: typeof options === 'object'
|
|
259
|
+
? Date.now() + (hInterval(options.refresh) || 3600)
|
|
260
|
+
: undefined
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private refreshStaticPages() {
|
|
266
|
+
|
|
267
|
+
console.log('[router] refreshStaticPages');
|
|
268
|
+
|
|
269
|
+
for (const pageId in this.cache) {
|
|
270
|
+
const page = this.cache[pageId];
|
|
271
|
+
if (page.expire && page.expire < Date.now()) {
|
|
272
|
+
|
|
273
|
+
this.renderStatic(page.path, page.options);
|
|
274
|
+
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
212
283
|
private registerRoutes(defModules: GlobImportedWithMetas<TRouteModule>) {
|
|
213
284
|
for (const routeModule of defModules) {
|
|
214
285
|
|
|
@@ -257,6 +328,14 @@ export default class ServerRouter
|
|
|
257
328
|
|
|
258
329
|
this.routes.push(route);
|
|
259
330
|
|
|
331
|
+
// Add to static pages
|
|
332
|
+
// Should be a GET oage that don't take any parameter
|
|
333
|
+
if (options.static) {
|
|
334
|
+
for (const url of options.static.urls) {
|
|
335
|
+
this.renderStatic(url, options.static);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
260
339
|
return this;
|
|
261
340
|
|
|
262
341
|
}
|
|
@@ -419,7 +498,13 @@ export default class ServerRouter
|
|
|
419
498
|
"Cache-Control",
|
|
420
499
|
"no-store, no-cache, must-revalidate, proxy-revalidate"
|
|
421
500
|
);
|
|
422
|
-
|
|
501
|
+
|
|
502
|
+
// Static pages
|
|
503
|
+
if (this.cache[req.path]) {
|
|
504
|
+
console.log('[router] Get static page from cache', req.path);
|
|
505
|
+
res.send( this.cache[req.path].rendered );
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
423
508
|
|
|
424
509
|
// Create request
|
|
425
510
|
let requestId = uuid();
|
|
@@ -578,6 +663,12 @@ export default class ServerRouter
|
|
|
578
663
|
if (!response.wasProvided)
|
|
579
664
|
return;
|
|
580
665
|
|
|
666
|
+
// Set in cache
|
|
667
|
+
if (route.options.static && route.options.static.urls.includes('*')) {
|
|
668
|
+
console.log('[router] Set in cache', response.request.path);
|
|
669
|
+
this.renderStatic(response.request.path, route.options.static, response.data);
|
|
670
|
+
}
|
|
671
|
+
|
|
581
672
|
const timeEndResolving = Date.now();
|
|
582
673
|
this.printTakenTime(timeStart, timeEndResolving);
|
|
583
674
|
}
|
|
@@ -111,17 +111,6 @@ export default class ServerResponse<
|
|
|
111
111
|
// Create response context for controllers
|
|
112
112
|
const context = await this.createContext(route);
|
|
113
113
|
|
|
114
|
-
// Static rendering
|
|
115
|
-
const chunkId = route.options["id"];
|
|
116
|
-
if (route.options.static &&
|
|
117
|
-
chunkId !== undefined
|
|
118
|
-
&&
|
|
119
|
-
this.router.cache[ chunkId ] !== undefined
|
|
120
|
-
) {
|
|
121
|
-
await this.html( this.router.cache[ chunkId ] );
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
114
|
// Run controller
|
|
126
115
|
const content = await this.route.controller( context );
|
|
127
116
|
if (content === undefined)
|
|
@@ -139,10 +128,6 @@ export default class ServerResponse<
|
|
|
139
128
|
// Return JSON
|
|
140
129
|
else
|
|
141
130
|
await this.json(content);
|
|
142
|
-
|
|
143
|
-
// Cache
|
|
144
|
-
if (route.options.static)
|
|
145
|
-
this.router.cache[ chunkId ] = this.data;
|
|
146
131
|
}
|
|
147
132
|
|
|
148
133
|
private updateCanonicalUrl( route: TAnyRoute ) {
|
package/types/icons.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type TIcones = "solid/spinner-third"|"long-arrow-right"|"times-circle"|"brands/whatsapp"|"times"|"
|
|
1
|
+
export type TIcones = "solid/spinner-third"|"long-arrow-right"|"times-circle"|"brands/whatsapp"|"times"|"user"|"rocket"|"globe"|"bullhorn"|"briefcase"|"chart-line"|"handshake"|"ellipsis-h"|"brands/google"|"brands/reddit-alien"|"brands/linkedin-in"|"brands/github"|"robot"|"comments"|"user-friends"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"search"|"angle-down"|"info-circle"|"check-circle"|"exclamation-circle"|"chart-bar"|"power-off"|"home"|"user-circle"|"newspaper"|"plus-circle"|"brands/linkedin"|"brands/twitter"|"brands/facebook"|"comment-alt"|"heart"|"lock"|"eye"|"credit-card"|"at"|"key"|"bars"|"font"|"tag"|"compress"|"bolt"|"puzzle-piece"|"planet-ringed"|"database"|"solid/fire"|"usd-circle"|"lightbulb"|"solid/dollar-sign"|"download"|"code"|"solid/clock"|"exclamation"|"solid/download"|"seedling"|"palette"|"car"|"plane"|"university"|"hard-hat"|"graduation-cap"|"cogs"|"film"|"leaf"|"tshirt"|"utensils"|"map-marked-alt"|"dumbbell"|"stethoscope"|"concierge-bell"|"book"|"shield-alt"|"gavel"|"industry"|"square-root-alt"|"pills"|"medal"|"capsules"|"balance-scale"|"praying-hands"|"shopping-cart"|"flask"|"futbol"|"microchip"|"satellite-dish"|"shipping-fast"|"passport"|"tools"|"angle-left"|"angle-right"|"check"|"paper-plane"|"trash"|"meh-rolling-eyes"|"arrow-left"|"arrow-right"|"unlink"|"pen"|"link"|"file"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"plus"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"
|