proteum 1.0.2 → 2.0.0-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/AGENTS.md +101 -0
- package/agents/codex/AGENTS.md +95 -0
- package/agents/codex/CODING_STYLE.md +71 -0
- package/agents/codex/agents.md.zip +0 -0
- package/agents/codex/client/AGENTS.md +102 -0
- package/agents/codex/client/pages/AGENTS.md +35 -0
- package/agents/codex/server/routes/AGENTS.md +12 -0
- package/agents/codex/server/services/AGENTS.md +137 -0
- package/agents/codex/tests/AGENTS.md +8 -0
- package/cli/app/config.ts +13 -11
- package/cli/app/index.ts +74 -82
- package/cli/bin.js +1 -1
- package/cli/commands/build.ts +51 -14
- package/cli/commands/check.ts +19 -0
- package/cli/commands/deploy/app.ts +4 -8
- package/cli/commands/deploy/web.ts +16 -20
- package/cli/commands/dev.ts +189 -64
- package/cli/commands/devEvents.ts +106 -0
- package/cli/commands/init.ts +63 -57
- package/cli/commands/lint.ts +21 -0
- package/cli/commands/refresh.ts +18 -0
- package/cli/commands/typecheck.ts +18 -0
- package/cli/compiler/client/identite.ts +80 -53
- package/cli/compiler/client/index.ts +139 -213
- package/cli/compiler/common/bundleAnalysis.ts +94 -0
- package/cli/compiler/common/clientManifest.ts +67 -0
- package/cli/compiler/common/controllers.ts +288 -0
- package/cli/compiler/common/files/autres.ts +7 -18
- package/cli/compiler/common/files/images.ts +40 -37
- package/cli/compiler/common/files/style.ts +11 -22
- package/cli/compiler/common/generatedRouteModules.ts +368 -0
- package/cli/compiler/common/index.ts +31 -65
- package/cli/compiler/common/loaders/forbid-ssr-import.js +13 -0
- package/cli/compiler/common/rspackAliases.ts +13 -0
- package/cli/compiler/common/scripts.ts +37 -0
- package/cli/compiler/index.ts +781 -230
- package/cli/compiler/server/index.ts +59 -75
- package/cli/compiler/writeIfChanged.ts +21 -0
- package/cli/index.ts +71 -72
- package/cli/paths.ts +51 -57
- package/cli/print.ts +17 -11
- package/cli/tsconfig.json +5 -4
- package/cli/utils/agents.ts +100 -0
- package/cli/utils/check.ts +71 -0
- package/cli/utils/index.ts +1 -3
- package/cli/utils/keyboard.ts +8 -25
- package/cli/utils/runProcess.ts +30 -0
- package/client/app/component.tsx +29 -29
- package/client/app/index.ts +36 -57
- package/client/app/service.ts +7 -12
- package/client/app.tsconfig.json +2 -2
- package/client/components/Dialog/Manager.ssr.tsx +40 -0
- package/client/components/Dialog/Manager.tsx +119 -150
- package/client/components/Dialog/status.tsx +3 -3
- package/client/components/index.ts +1 -1
- package/client/components/types.d.ts +1 -3
- package/client/dev/hmr.ts +65 -0
- package/client/global.d.ts +2 -2
- package/client/hooks.ts +6 -9
- package/client/index.ts +2 -1
- package/client/islands/index.ts +7 -0
- package/client/islands/useDeferredModule.ts +199 -0
- package/client/pages/_layout/index.tsx +4 -12
- package/client/pages/useHeader.tsx +14 -21
- package/client/router.ts +27 -0
- package/client/services/router/components/Link.tsx +34 -27
- package/client/services/router/components/Page.tsx +6 -14
- package/client/services/router/components/router.ssr.tsx +36 -0
- package/client/services/router/components/router.tsx +63 -83
- package/client/services/router/index.tsx +185 -220
- package/client/services/router/request/api.ts +97 -119
- package/client/services/router/request/history.ts +2 -2
- package/client/services/router/request/index.ts +13 -12
- package/client/services/router/request/multipart.ts +72 -62
- package/client/services/router/response/index.tsx +68 -61
- package/client/services/router/response/page.ts +28 -32
- package/client/utils/dom.ts +17 -33
- package/common/app/index.ts +3 -3
- package/common/data/chaines/index.ts +22 -23
- package/common/data/dates.ts +35 -70
- package/common/data/markdown.ts +42 -39
- package/common/dev/serverHotReload.ts +26 -0
- package/common/errors/index.tsx +110 -142
- package/common/router/contracts.ts +29 -0
- package/common/router/index.ts +89 -108
- package/common/router/layouts.ts +34 -47
- package/common/router/pageSetup.ts +50 -0
- package/common/router/register.ts +53 -24
- package/common/router/request/api.ts +30 -36
- package/common/router/request/index.ts +2 -8
- package/common/router/response/index.ts +8 -15
- package/common/router/response/page.ts +70 -58
- package/common/utils.ts +1 -1
- package/doc/TODO.md +1 -1
- package/eslint.js +62 -0
- package/package.json +14 -49
- package/prettier.config.cjs +9 -0
- package/scripts/cleanup-generated-controllers.ts +62 -0
- package/scripts/fix-reference-app-typing.ts +490 -0
- package/scripts/refactor-client-app-imports.ts +244 -0
- package/scripts/refactor-client-pages.ts +587 -0
- package/scripts/refactor-server-controllers.ts +470 -0
- package/scripts/refactor-server-runtime-aliases.ts +360 -0
- package/scripts/restore-client-app-import-files.ts +41 -0
- package/scripts/restore-files-from-git-head.ts +20 -0
- package/scripts/update-codex-agents.ts +35 -0
- package/server/app/commands.ts +35 -64
- package/server/app/container/config.ts +48 -59
- package/server/app/container/console/index.ts +202 -248
- package/server/app/container/index.ts +33 -71
- package/server/app/controller/index.ts +61 -0
- package/server/app/index.ts +39 -105
- package/server/app/service/container.ts +41 -42
- package/server/app/service/index.ts +120 -147
- package/server/context.ts +1 -1
- package/server/index.ts +25 -1
- package/server/services/auth/index.ts +75 -115
- package/server/services/auth/router/index.ts +31 -32
- package/server/services/auth/router/request.ts +14 -16
- package/server/services/cron/CronTask.ts +13 -26
- package/server/services/cron/index.ts +14 -36
- package/server/services/disks/driver.ts +40 -58
- package/server/services/disks/drivers/local/index.ts +79 -90
- package/server/services/disks/drivers/s3/index.ts +116 -163
- package/server/services/disks/index.ts +23 -38
- package/server/services/email/index.ts +45 -104
- package/server/services/email/utils.ts +14 -27
- package/server/services/fetch/index.ts +53 -85
- package/server/services/prisma/Facet.ts +39 -91
- package/server/services/prisma/index.ts +74 -110
- package/server/services/router/generatedRuntime.ts +29 -0
- package/server/services/router/http/index.ts +78 -73
- package/server/services/router/http/multipart.ts +19 -42
- package/server/services/router/index.ts +378 -365
- package/server/services/router/request/api.ts +26 -25
- package/server/services/router/request/index.ts +44 -51
- package/server/services/router/request/service.ts +7 -11
- package/server/services/router/request/validation/zod.ts +111 -148
- package/server/services/router/response/index.ts +110 -125
- package/server/services/router/response/mask/Filter.ts +31 -72
- package/server/services/router/response/mask/index.ts +8 -15
- package/server/services/router/response/mask/selecteurs.ts +11 -25
- package/server/services/router/response/page/clientManifest.ts +25 -0
- package/server/services/router/response/page/document.tsx +199 -127
- package/server/services/router/response/page/index.tsx +89 -94
- package/server/services/router/service.ts +13 -15
- package/server/services/schema/index.ts +17 -26
- package/server/services/schema/request.ts +19 -33
- package/server/services/schema/router/index.ts +8 -11
- package/server/services/security/encrypt/aes/index.ts +15 -35
- package/server/utils/slug.ts +29 -35
- package/skills/clean-project-code/SKILL.md +63 -0
- package/skills/clean-project-code/agents/openai.yaml +4 -0
- package/tsconfig.common.json +4 -3
- package/tsconfig.json +4 -1
- package/types/aliases.d.ts +17 -21
- package/types/controller-input.test.ts +48 -0
- package/types/express-extra.d.ts +6 -0
- package/types/global/constants.d.ts +13 -0
- package/types/global/express-extra.d.ts +6 -0
- package/types/global/modules.d.ts +13 -16
- package/types/global/utils.d.ts +17 -49
- package/types/global/vendors.d.ts +62 -0
- package/types/icons.d.ts +65 -1
- package/types/uuid.d.ts +3 -0
- package/types/vendors.d.ts +62 -0
- package/cli/compiler/common/babel/index.ts +0 -170
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +0 -586
- package/cli/compiler/common/babel/routes/imports.ts +0 -127
- package/cli/compiler/common/babel/routes/routes.ts +0 -1130
- package/client/services/captcha/index.ts +0 -67
- package/client/services/socket/index.ts +0 -147
- package/common/data/rte/nodes.ts +0 -83
- package/common/data/stats.ts +0 -90
- package/common/utils/rte.ts +0 -183
- package/server/services/auth/old.ts +0 -277
- package/server/services/cache/commands.ts +0 -41
- package/server/services/cache/index.ts +0 -297
- package/server/services/cache/service.json +0 -6
- package/server/services/socket/index.ts +0 -162
- package/server/services/socket/scope.ts +0 -226
- package/server/services/socket/service.json +0 -6
- package/server/services_old/SocketClient.ts +0 -92
- package/server/services_old/Token.old.ts +0 -97
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
5
|
// Libs
|
|
6
|
-
import compilerSelecteurs, { TObjetSelecteurs } from './selecteurs';
|
|
6
|
+
import compilerSelecteurs, { TObjetSelecteurs, TSelecteur } from './selecteurs';
|
|
7
7
|
import Filter from './Filter';
|
|
8
8
|
|
|
9
9
|
// Filtres spécifiques métier
|
|
@@ -24,24 +24,18 @@ const debug = false;
|
|
|
24
24
|
----------------------------------*/
|
|
25
25
|
|
|
26
26
|
// proprieteModele = Si l'objet actuellement traité fait partie des valeurs d'un modèle
|
|
27
|
-
export default (
|
|
28
|
-
donnee: any,
|
|
29
|
-
selecteurs?: string | TObjetSelecteurs
|
|
30
|
-
) => {
|
|
31
|
-
|
|
27
|
+
export default (donnee: any, selecteurs?: string | TObjetSelecteurs) => {
|
|
32
28
|
// Pas besoin de filtrer
|
|
33
|
-
if (donnee === null || typeof donnee !== 'object'/* || donnee._filtered === true */) {
|
|
29
|
+
if (donnee === null || typeof donnee !== 'object' /* || donnee._filtered === true */) {
|
|
34
30
|
return donnee;
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
// Correction sélecteurs
|
|
38
|
-
let selecteursCompiles:
|
|
39
|
-
if (selecteurs === undefined)
|
|
40
|
-
selecteursCompiles = undefined;
|
|
34
|
+
let selecteursCompiles: TSelecteur | undefined;
|
|
35
|
+
if (selecteurs === undefined) selecteursCompiles = undefined;
|
|
41
36
|
else if (typeof selecteurs === 'string')
|
|
42
|
-
selecteursCompiles = compilerSelecteurs(selecteurs);
|
|
43
|
-
else
|
|
44
|
-
selecteursCompiles = selecteurs;
|
|
37
|
+
selecteursCompiles = compilerSelecteurs(selecteurs); // Déjà un objet, pas besoin de compiler
|
|
38
|
+
else selecteursCompiles = selecteurs;
|
|
45
39
|
|
|
46
40
|
debug && console.log('Avant filtrage', donnee);
|
|
47
41
|
|
|
@@ -56,5 +50,4 @@ export default (
|
|
|
56
50
|
debug && console.log('Apres filtrage', retour);
|
|
57
51
|
|
|
58
52
|
return retour;
|
|
59
|
-
|
|
60
|
-
}
|
|
53
|
+
};
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
/*----------------------------------
|
|
6
6
|
- TYPES
|
|
7
7
|
----------------------------------*/
|
|
8
|
-
export type TSelecteur = true |
|
|
8
|
+
export type TSelecteur = true | '*' | TObjetSelecteurs;
|
|
9
9
|
// Wildcard en clé = selectionner toutes les clés
|
|
10
10
|
// Wildcard en valeur = sélectionner absolument toutes les valeur descendantes
|
|
11
|
-
export type TObjetSelecteurs = {[cle: string]: TSelecteur}
|
|
11
|
+
export type TObjetSelecteurs = { [cle: string]: TSelecteur };
|
|
12
12
|
|
|
13
13
|
/*----------------------------------
|
|
14
14
|
- CONSTANTES
|
|
@@ -21,66 +21,53 @@ const cache: TObjetSelecteurs = {};
|
|
|
21
21
|
- FONCTION
|
|
22
22
|
----------------------------------*/
|
|
23
23
|
export default (selecteurs: string) => {
|
|
24
|
-
|
|
25
|
-
if (cache[selecteurs] === undefined)
|
|
26
|
-
cache[selecteurs] = compiler(selecteurs);
|
|
24
|
+
if (cache[selecteurs] === undefined) cache[selecteurs] = compiler(selecteurs);
|
|
27
25
|
|
|
28
26
|
return cache[selecteurs];
|
|
29
|
-
|
|
30
|
-
}
|
|
27
|
+
};
|
|
31
28
|
|
|
32
29
|
const compiler = (selecteurs: string): TObjetSelecteurs => {
|
|
33
|
-
|
|
34
30
|
let chemins: TObjetSelecteurs = {};
|
|
35
31
|
let cheminA: string[] = []; // Chemin en construction
|
|
36
32
|
|
|
37
33
|
let branche;
|
|
38
|
-
while (branche = reSelecteurs.exec(selecteurs)) {
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
while ((branche = reSelecteurs.exec(selecteurs))) {
|
|
35
|
+
if (branche[0] === ')') {
|
|
36
|
+
// fermeture
|
|
41
37
|
|
|
42
38
|
// Niveau précédent: docs.titre => docs
|
|
43
39
|
cheminA.pop();
|
|
44
|
-
|
|
45
40
|
} else {
|
|
46
|
-
|
|
47
41
|
const nomBranche = branche[2];
|
|
48
42
|
const ouverture = branche[5] === '(';
|
|
49
43
|
|
|
50
44
|
// Ligne débutant par un # = commentaire
|
|
51
|
-
if (nomBranche.startsWith(
|
|
52
|
-
continue;
|
|
45
|
+
if (nomBranche.startsWith('#')) continue;
|
|
53
46
|
|
|
54
47
|
if (ouverture)
|
|
55
48
|
// Ouverture de la branche: docs => docs.titre
|
|
56
49
|
cheminA.push(nomBranche);
|
|
57
50
|
else {
|
|
58
|
-
|
|
59
51
|
const chemin = [...cheminA, nomBranche];
|
|
60
52
|
|
|
61
53
|
// Construction du chemin
|
|
62
54
|
let brancheA = chemins;
|
|
63
55
|
const nbBranches = chemin.length;
|
|
64
56
|
for (let iBranche = 0; iBranche < nbBranches; iBranche++) {
|
|
65
|
-
|
|
66
57
|
const nomBranche = chemin[iBranche];
|
|
67
58
|
|
|
68
|
-
const extremite = iBranche === nbBranches - 1
|
|
59
|
+
const extremite = iBranche === nbBranches - 1;
|
|
69
60
|
if (extremite) {
|
|
70
|
-
|
|
71
61
|
// Dernière branche = extremité = true
|
|
72
62
|
brancheA[nomBranche] = true;
|
|
73
|
-
|
|
74
63
|
} else {
|
|
75
|
-
|
|
76
64
|
// Pas encore définie
|
|
77
65
|
if (brancheA[nomBranche] === undefined)
|
|
78
66
|
// Sinon, initialisation
|
|
79
67
|
brancheA[nomBranche] = {};
|
|
80
68
|
|
|
81
69
|
// Rférnce pour la prochaine itération
|
|
82
|
-
brancheA = brancheA[nomBranche];
|
|
83
|
-
|
|
70
|
+
brancheA = brancheA[nomBranche] as TObjetSelecteurs;
|
|
84
71
|
}
|
|
85
72
|
}
|
|
86
73
|
}
|
|
@@ -88,5 +75,4 @@ const compiler = (selecteurs: string): TObjetSelecteurs => {
|
|
|
88
75
|
}
|
|
89
76
|
|
|
90
77
|
return chemins;
|
|
91
|
-
|
|
92
|
-
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
type TClientManifestAssets = { assets?: string[]; css?: string[]; js?: string[] };
|
|
5
|
+
|
|
6
|
+
export type TClientBuildManifest = {
|
|
7
|
+
publicPath?: string;
|
|
8
|
+
entries?: Record<string, TClientManifestAssets>;
|
|
9
|
+
chunks?: Record<string, TClientManifestAssets>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const manifestPath = path.join(__dirname, 'client-manifest.json');
|
|
13
|
+
let cachedManifest: TClientBuildManifest | undefined;
|
|
14
|
+
|
|
15
|
+
export const getClientBuildManifest = (): TClientBuildManifest => {
|
|
16
|
+
if (!__DEV__) {
|
|
17
|
+
if (!cachedManifest) {
|
|
18
|
+
cachedManifest = fs.existsSync(manifestPath) ? fs.readJSONSync(manifestPath) : {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return cachedManifest ?? {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return fs.existsSync(manifestPath) ? fs.readJSONSync(manifestPath) : {};
|
|
25
|
+
};
|
|
@@ -4,157 +4,229 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import React from 'react';
|
|
7
|
-
import renderToString from
|
|
7
|
+
import renderToString from 'preact-render-to-string';
|
|
8
8
|
const safeStringify = require('fast-safe-stringify'); // remplace les références circulairs par un [Circular]
|
|
9
9
|
|
|
10
10
|
// Core
|
|
11
|
-
import type {
|
|
11
|
+
import type { TServerRouter, Response as ServerResponse } from '@server/services/router';
|
|
12
12
|
import type Page from '.';
|
|
13
|
+
import { getClientBuildManifest } from './clientManifest';
|
|
13
14
|
|
|
14
15
|
/*----------------------------------
|
|
15
16
|
- TYPES
|
|
16
17
|
----------------------------------*/
|
|
17
18
|
|
|
18
|
-
|
|
19
19
|
/*----------------------------------
|
|
20
20
|
- SERVICE
|
|
21
21
|
----------------------------------*/
|
|
22
|
-
export default class DocumentRenderer<TRouter extends
|
|
23
|
-
|
|
22
|
+
export default class DocumentRenderer<TRouter extends TServerRouter> {
|
|
24
23
|
public constructor(
|
|
25
24
|
public router: TRouter,
|
|
26
|
-
public app = router.app
|
|
27
|
-
) {
|
|
25
|
+
public app = router.app,
|
|
26
|
+
) {}
|
|
28
27
|
|
|
28
|
+
public staticDocument() {
|
|
29
|
+
const routesForClient = JSON.stringify(this.router.ssrRoutes);
|
|
30
|
+
return (
|
|
31
|
+
'<!doctype html>' +
|
|
32
|
+
renderToString(
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
{/* Format */}
|
|
36
|
+
<meta charSet="utf-8" />
|
|
37
|
+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
|
|
38
|
+
|
|
39
|
+
{/* CSS */}
|
|
40
|
+
{this.clientStyles()}
|
|
41
|
+
<link rel="preload" as="font" href={'/public/icons.woff2?v=' + BUILD_ID} type="font/woff2" />
|
|
42
|
+
<link rel="stylesheet" type="text/css" href="/public/icons.css" />
|
|
43
|
+
|
|
44
|
+
{/* JS */}
|
|
45
|
+
<script
|
|
46
|
+
type="text/javascript"
|
|
47
|
+
dangerouslySetInnerHTML={{
|
|
48
|
+
__html:
|
|
49
|
+
`window.routes=${routesForClient};` +
|
|
50
|
+
(this.app.env.profile === 'dev' ? 'window.dev = true;' : ''),
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
{this.clientScripts()}
|
|
54
|
+
</head>
|
|
55
|
+
<body></body>
|
|
56
|
+
</html>,
|
|
57
|
+
)
|
|
58
|
+
);
|
|
29
59
|
}
|
|
30
60
|
|
|
31
|
-
public
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
public async page(html: string, page: Page<TRouter>, response: ServerResponse<TRouter>) {
|
|
62
|
+
let attrsBody = { className: [...page.bodyClass].join(' ') };
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
'<!doctype html>' +
|
|
66
|
+
renderToString(
|
|
67
|
+
<html lang="en">
|
|
68
|
+
<head>
|
|
69
|
+
{/* Format */}
|
|
70
|
+
<meta charSet="utf-8" />
|
|
71
|
+
<meta content="IE=edge" httpEquiv="X-UA-Compatible" />
|
|
72
|
+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
|
|
73
|
+
|
|
74
|
+
{/* Mobile */}
|
|
75
|
+
<meta name="application-name" content={this.app.identity.web.title} />
|
|
76
|
+
<meta name="apple-mobile-web-app-title" content={this.app.identity.web.title} />
|
|
77
|
+
<meta name="apple-mobile-web-app-title" content={this.app.identity.web.title} />
|
|
78
|
+
<meta content={this.app.identity.author.name} name="author" />
|
|
79
|
+
<meta name="theme-color" content={this.app.identity.maincolor} />
|
|
80
|
+
<meta name="msapplication-TileColor" content={this.app.identity.maincolor} />
|
|
81
|
+
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
82
|
+
<meta name="mobile-web-app-capable" content="yes" />
|
|
83
|
+
<meta
|
|
84
|
+
name="viewport"
|
|
85
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
{/* https://stackoverflow.com/questions/48956465/favicon-standard-2019-svg-ico-png-and-dimensions */}
|
|
89
|
+
{/*<link rel="manifest" href={RES['manifest.json']} />*/}
|
|
90
|
+
<link rel="shortcut icon" href="/public/app/favicon.ico" />
|
|
91
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/public/app/favicon-16x16.png" />
|
|
92
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/public/app/favicon-32x32.png" />
|
|
93
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/public/app/apple-touch-icon-180x180.png" />
|
|
94
|
+
<meta name="msapplication-config" content="/public/app/browserconfig.xml" />
|
|
95
|
+
|
|
96
|
+
{/* Page */}
|
|
97
|
+
<title>{page.title}</title>
|
|
98
|
+
<meta content={page.description} name="description" />
|
|
99
|
+
<link rel="canonical" href={String(response.canonicalUrl)} />
|
|
100
|
+
|
|
101
|
+
{/* SEO, social medias, OG tags, ... */}
|
|
102
|
+
{page.head.map(({ $, ...attrs }) => React.createElement($, attrs))}
|
|
103
|
+
|
|
104
|
+
{this.styles(page)}
|
|
105
|
+
|
|
106
|
+
{await this.scripts(response, page)}
|
|
107
|
+
|
|
108
|
+
{/* Rich Snippets: https://schema.org/docs/full.html + https://jsonld.com/ */}
|
|
109
|
+
<script
|
|
110
|
+
type="application/ld+json"
|
|
111
|
+
dangerouslySetInnerHTML={{
|
|
112
|
+
__html: JSON.stringify({ '@context': 'http://schema.org', '@graph': page.jsonld }),
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
</head>
|
|
116
|
+
<body {...attrsBody} dangerouslySetInnerHTML={{ __html: html }}></body>
|
|
117
|
+
</html>,
|
|
118
|
+
)
|
|
56
119
|
);
|
|
57
120
|
}
|
|
58
121
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<meta name="theme-color" content={this.app.identity.maincolor} />
|
|
79
|
-
<meta name="msapplication-TileColor" content={this.app.identity.maincolor} />
|
|
80
|
-
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
81
|
-
<meta name="mobile-web-app-capable" content="yes" />
|
|
82
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
|
83
|
-
|
|
84
|
-
{/* https://stackoverflow.com/questions/48956465/favicon-standard-2019-svg-ico-png-and-dimensions */}
|
|
85
|
-
{/*<link rel="manifest" href={RES['manifest.json']} />*/}
|
|
86
|
-
<link rel="shortcut icon" href="/public/app/favicon.ico" />
|
|
87
|
-
<link rel="icon" type="image/png" sizes="16x16" href="/public/app/favicon-16x16.png" />
|
|
88
|
-
<link rel="icon" type="image/png" sizes="32x32" href="/public/app/favicon-32x32.png" />
|
|
89
|
-
<link rel="apple-touch-icon" sizes="180x180" href="/public/app/apple-touch-icon-180x180.png" />
|
|
90
|
-
<meta name="msapplication-config" content="/public/app/browserconfig.xml" />
|
|
91
|
-
|
|
92
|
-
{/* Page */}
|
|
93
|
-
<title>{page.title}</title>
|
|
94
|
-
<meta content={page.description} name="description" />
|
|
95
|
-
<link rel="canonical" href={response.canonicalUrl} />
|
|
96
|
-
|
|
97
|
-
{/* SEO, social medias, OG tags, ... */}
|
|
98
|
-
{page.head.map(({ $, ...attrs }) => (
|
|
99
|
-
React.createElement($, attrs)
|
|
100
|
-
))}
|
|
101
|
-
|
|
102
|
-
{this.styles( page )}
|
|
103
|
-
|
|
104
|
-
{await this.scripts( response, page )}
|
|
105
|
-
|
|
106
|
-
{/* Rich Snippets: https://schema.org/docs/full.html + https://jsonld.com/ */}
|
|
107
|
-
<script type="application/ld+json" dangerouslySetInnerHTML={{
|
|
108
|
-
__html: JSON.stringify({
|
|
109
|
-
'@context': 'http://schema.org',
|
|
110
|
-
'@graph': page.jsonld
|
|
111
|
-
})
|
|
112
|
-
}}/>
|
|
113
|
-
|
|
114
|
-
</head>
|
|
115
|
-
<body {...attrsBody} dangerouslySetInnerHTML={{ __html: html }}></body>
|
|
116
|
-
</html>
|
|
117
|
-
)
|
|
122
|
+
private styles(page: Page<TRouter>) {
|
|
123
|
+
return (
|
|
124
|
+
<>
|
|
125
|
+
{this.clientStyles()}
|
|
126
|
+
|
|
127
|
+
{page.style.map((style) =>
|
|
128
|
+
'url' in style ? (
|
|
129
|
+
<>
|
|
130
|
+
<link rel="preload" href={style.url} as="style" />
|
|
131
|
+
<link rel="stylesheet" type="text/css" href={style.url} />
|
|
132
|
+
</>
|
|
133
|
+
) : (
|
|
134
|
+
<>
|
|
135
|
+
<style id={style.id} dangerouslySetInnerHTML={{ __html: style.inline }} />
|
|
136
|
+
</>
|
|
137
|
+
),
|
|
138
|
+
)}
|
|
139
|
+
</>
|
|
140
|
+
);
|
|
118
141
|
}
|
|
119
142
|
|
|
120
|
-
private
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
private clientStyles() {
|
|
144
|
+
const styles = this.clientEntryAssets('css');
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<>
|
|
148
|
+
{styles.map((style) => {
|
|
149
|
+
const href = this.clientAssetUrl(style);
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<React.Fragment key={style}>
|
|
153
|
+
<link rel="preload" href={href} as="style" />
|
|
154
|
+
<link rel="stylesheet" type="text/css" href={href} />
|
|
155
|
+
</React.Fragment>
|
|
156
|
+
);
|
|
157
|
+
})}
|
|
158
|
+
</>
|
|
159
|
+
);
|
|
132
160
|
}
|
|
133
161
|
|
|
134
|
-
private
|
|
162
|
+
private clientScripts() {
|
|
163
|
+
const scripts = this.clientEntryAssets('js');
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<>
|
|
167
|
+
{scripts.map((script) => {
|
|
168
|
+
const src = this.clientAssetUrl(script, true);
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<React.Fragment key={script}>
|
|
172
|
+
<link rel="preload" href={src} as="script" />
|
|
173
|
+
<script defer type="text/javascript" src={src} />
|
|
174
|
+
</React.Fragment>
|
|
175
|
+
);
|
|
176
|
+
})}
|
|
177
|
+
</>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
135
180
|
|
|
181
|
+
private async scripts(response: ServerResponse<TRouter>, page: Page<TRouter>) {
|
|
136
182
|
const ssrData = response.forSsr(page);
|
|
137
|
-
const context = safeStringify(
|
|
138
|
-
const routesForClient = JSON.stringify(
|
|
139
|
-
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
183
|
+
const context = safeStringify(ssrData);
|
|
184
|
+
const routesForClient = JSON.stringify(this.router.ssrRoutes);
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<>
|
|
188
|
+
{/* JS */}
|
|
189
|
+
<script
|
|
190
|
+
type="text/javascript"
|
|
191
|
+
dangerouslySetInnerHTML={{
|
|
192
|
+
__html:
|
|
193
|
+
`window.ssr=${context}; window.routes=${routesForClient};` +
|
|
194
|
+
(this.app.env.profile === 'dev' ? 'window.dev = true;' : ''),
|
|
195
|
+
}}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
{this.clientScripts()}
|
|
199
|
+
|
|
200
|
+
{page.scripts.map((script) =>
|
|
201
|
+
'url' in script ? (
|
|
202
|
+
<>
|
|
203
|
+
<link rel="preload" href={script.url} as="script" />
|
|
204
|
+
<script type="text/javascript" src={script.url} {...(script.attrs || {})} />
|
|
205
|
+
</>
|
|
206
|
+
) : (
|
|
207
|
+
<>
|
|
208
|
+
<script
|
|
209
|
+
type="text/javascript"
|
|
210
|
+
{...(script.attrs || {})}
|
|
211
|
+
id={script.id}
|
|
212
|
+
dangerouslySetInnerHTML={{ __html: script.inline }}
|
|
213
|
+
/>
|
|
214
|
+
</>
|
|
215
|
+
),
|
|
216
|
+
)}
|
|
217
|
+
</>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private clientEntryAssets(kind: 'assets' | 'css' | 'js' = 'assets'): string[] {
|
|
222
|
+
const manifest = getClientBuildManifest();
|
|
223
|
+
const entry = manifest.entries?.client;
|
|
224
|
+
const assets = entry?.[kind];
|
|
225
|
+
|
|
226
|
+
return Array.isArray(assets) ? assets : [];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private clientAssetUrl(asset: string, withBuildId = false) {
|
|
230
|
+
return `/public/${asset}${withBuildId ? `?v=${BUILD_ID}` : ''}`;
|
|
159
231
|
}
|
|
160
|
-
}
|
|
232
|
+
}
|