proteum 1.0.3 → 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/AGENTS.md +92 -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 +12 -17
- package/cli/app/index.ts +59 -99
- package/cli/bin.js +1 -1
- package/cli/commands/build.ts +23 -12
- 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 +185 -75
- 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 +6 -6
- package/cli/commands/typecheck.ts +18 -0
- package/cli/compiler/client/identite.ts +79 -49
- package/cli/compiler/client/index.ts +132 -214
- 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 +12 -25
- package/cli/compiler/common/generatedRouteModules.ts +368 -0
- package/cli/compiler/common/index.ts +29 -68
- 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 +764 -234
- package/cli/compiler/server/index.ts +52 -77
- package/cli/compiler/writeIfChanged.ts +21 -0
- package/cli/index.ts +65 -90
- 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/eslint.js +62 -0
- package/package.json +12 -45
- 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 +39 -69
- 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 +77 -72
- 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 -32
- 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 +1 -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 -173
- 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 -1170
- 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
|
@@ -4,78 +4,76 @@
|
|
|
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
|
|
|
9
9
|
// Core
|
|
10
|
-
import {
|
|
10
|
+
import { type TServerRouter, TRouterContext } from '@server/services/router';
|
|
11
11
|
import type { Layout, TRoute, TErrorRoute, TClientOrServerContext } from '@common/router';
|
|
12
|
-
import PageResponse, { TFrontRenderer } from
|
|
12
|
+
import PageResponse, { TFrontRenderer, TPageRenderContext } from '@common/router/response/page';
|
|
13
|
+
import { getClientBuildManifest } from './clientManifest';
|
|
13
14
|
|
|
14
15
|
// Composants UI
|
|
15
16
|
import App from '@client/app/component';
|
|
16
17
|
|
|
17
|
-
// Caches
|
|
18
|
-
const chunks = require('./chunk-manifest.json');
|
|
19
|
-
|
|
20
18
|
/*----------------------------------
|
|
21
|
-
-
|
|
19
|
+
- CONSTANTS
|
|
22
20
|
----------------------------------*/
|
|
23
21
|
|
|
24
|
-
const seoLimits = {
|
|
25
|
-
title: 70,
|
|
26
|
-
description: 255
|
|
27
|
-
}
|
|
22
|
+
const seoLimits = { title: 70, description: 255 };
|
|
28
23
|
|
|
29
24
|
/*----------------------------------
|
|
30
|
-
-
|
|
25
|
+
- CLASS
|
|
31
26
|
----------------------------------*/
|
|
32
27
|
|
|
33
|
-
export default class ServerPage<TRouter extends
|
|
28
|
+
export default class ServerPage<TRouter extends TServerRouter = TServerRouter> extends PageResponse<
|
|
29
|
+
TRouter,
|
|
30
|
+
TRoute | TErrorRoute,
|
|
31
|
+
TRouterContext<TRouter>
|
|
32
|
+
> {
|
|
33
|
+
public app: TRouter['app'];
|
|
34
|
+
public router: TRouter;
|
|
35
|
+
|
|
36
|
+
/*----------------------------------
|
|
37
|
+
- PUBLIC API
|
|
38
|
+
----------------------------------*/
|
|
34
39
|
|
|
35
40
|
public constructor(
|
|
36
41
|
public route: TRoute | TErrorRoute,
|
|
37
42
|
public renderer: TFrontRenderer,
|
|
38
|
-
|
|
43
|
+
context: TRouterContext<TRouter>,
|
|
39
44
|
public layout?: Layout,
|
|
40
|
-
|
|
41
|
-
public app = context.app,
|
|
42
|
-
public router = context.request.router,
|
|
43
|
-
|
|
44
45
|
) {
|
|
46
|
+
super(route, renderer, context);
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
this.app = context.app;
|
|
49
|
+
this.router = context.request.router;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
public render(): Promise<string> {
|
|
51
|
-
|
|
52
53
|
// Complete SEO metadatas
|
|
53
|
-
const titleSuffix = ' | ' + this.app.identity.web.titleSuffix
|
|
54
|
-
if (this.title === undefined)
|
|
55
|
-
|
|
56
|
-
else if (this.title.length < seoLimits.title - titleSuffix.length)
|
|
57
|
-
this.title += titleSuffix;
|
|
54
|
+
const titleSuffix = ' | ' + this.app.identity.web.titleSuffix;
|
|
55
|
+
if (this.title === undefined) this.title = this.app.identity.web.fullTitle;
|
|
56
|
+
else if (this.title.length < seoLimits.title - titleSuffix.length) this.title += titleSuffix;
|
|
58
57
|
|
|
59
|
-
if (this.description === undefined)
|
|
60
|
-
this.description = this.app.identity.web.description;
|
|
58
|
+
if (this.description === undefined) this.description = this.app.identity.web.description;
|
|
61
59
|
|
|
62
60
|
// We render page & document separatly,
|
|
63
61
|
// because document needs to access to runtime assigned values
|
|
64
62
|
// Ex: runtime added scripts, title, metas, ....
|
|
65
|
-
|
|
63
|
+
|
|
64
|
+
const context = this.context as TPageRenderContext & TRouterContext<TRouter>;
|
|
66
65
|
const html = renderToString(
|
|
67
|
-
<App {
|
|
66
|
+
<App context={context as Parameters<typeof App>[0]['context'] & TRouterContext<TRouter>} />,
|
|
68
67
|
);
|
|
69
68
|
|
|
70
|
-
if (html === undefined)
|
|
71
|
-
throw new Error(`Page HTML is empty (undefined)`);
|
|
69
|
+
if (html === undefined) throw new Error(`Page HTML is empty (undefined)`);
|
|
72
70
|
|
|
73
71
|
// Metas
|
|
74
72
|
this.buildMetas();
|
|
75
73
|
this.buildJsonLd();
|
|
76
74
|
|
|
77
|
-
//
|
|
78
|
-
//
|
|
75
|
+
// A page chunk can group multiple CSS and JS assets.
|
|
76
|
+
// Route ids come from the generated route wrapper modules.
|
|
79
77
|
this.addChunks();
|
|
80
78
|
|
|
81
79
|
/*if (page.classeBody)
|
|
@@ -84,46 +82,43 @@ export default class ServerPage<TRouter extends Router = Router> extends PageRes
|
|
|
84
82
|
if (page.theme)
|
|
85
83
|
attrsBody.className += ' ' + page.theme;*/
|
|
86
84
|
|
|
87
|
-
return this.router.render.page(html, this,
|
|
85
|
+
return this.router.render.page(html, this, context.response);
|
|
88
86
|
}
|
|
89
87
|
|
|
88
|
+
/*----------------------------------
|
|
89
|
+
- HELPERS
|
|
90
|
+
----------------------------------*/
|
|
91
|
+
|
|
90
92
|
// Define which chunks (script / style) to load
|
|
91
93
|
private addChunks() {
|
|
92
|
-
const
|
|
94
|
+
const manifest = getClientBuildManifest();
|
|
95
|
+
const pageChunks = [this.route.options['id']];
|
|
93
96
|
for (const chunk of pageChunks) {
|
|
94
|
-
|
|
95
97
|
if (!chunk) continue;
|
|
96
98
|
|
|
97
|
-
const assets = chunks[chunk];
|
|
99
|
+
const assets = manifest.chunks?.[chunk];
|
|
98
100
|
if (!assets) {
|
|
99
|
-
console.warn(
|
|
101
|
+
console.warn(
|
|
102
|
+
`Chunk ${chunk} was not found. Indexed chunks: ${Object.keys(manifest.chunks || {}).join(', ')}`,
|
|
103
|
+
);
|
|
100
104
|
continue;
|
|
101
105
|
}
|
|
102
106
|
|
|
103
|
-
for (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (asset.endsWith('.css'))
|
|
107
|
-
this.style.push({
|
|
108
|
-
id: chunk,
|
|
109
|
-
url: '/public/' + asset
|
|
110
|
-
})
|
|
111
|
-
else
|
|
112
|
-
this.scripts.push({
|
|
113
|
-
id: chunk,
|
|
114
|
-
url: '/public/' + asset
|
|
115
|
-
});
|
|
107
|
+
for (const asset of assets.css || []) {
|
|
108
|
+
this.style.push({ id: chunk, url: '/public/' + asset });
|
|
116
109
|
}
|
|
117
110
|
|
|
111
|
+
for (const asset of assets.js || []) {
|
|
112
|
+
this.scripts.push({ id: chunk, url: '/public/' + asset });
|
|
113
|
+
}
|
|
118
114
|
}
|
|
119
115
|
}
|
|
120
116
|
|
|
121
117
|
private buildMetas() {
|
|
118
|
+
const context = this.context as TPageRenderContext & TRouterContext<TRouter>;
|
|
119
|
+
const shouldIndex = context.response.statusCode < 300;
|
|
122
120
|
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
const metas = {
|
|
126
|
-
|
|
121
|
+
const metas: Record<string, string | undefined> = {
|
|
127
122
|
robots: shouldIndex ? 'index' : 'noindex',
|
|
128
123
|
|
|
129
124
|
'og:type': 'website',
|
|
@@ -141,56 +136,56 @@ export default class ServerPage<TRouter extends Router = Router> extends PageRes
|
|
|
141
136
|
|
|
142
137
|
...(this.app.identity.web.metas || {}),
|
|
143
138
|
|
|
144
|
-
...this.metas
|
|
139
|
+
...this.metas,
|
|
145
140
|
};
|
|
146
141
|
|
|
147
142
|
for (const key in metas) {
|
|
148
143
|
const value = metas[key];
|
|
149
|
-
if (value ===
|
|
144
|
+
if (value === '') continue;
|
|
150
145
|
this.head.push({ $: 'meta', property: key, content: value });
|
|
151
146
|
}
|
|
152
147
|
}
|
|
153
148
|
|
|
154
149
|
private buildJsonLd() {
|
|
155
|
-
this.jsonld.push(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
150
|
+
this.jsonld.push(
|
|
151
|
+
{
|
|
152
|
+
'@type': 'Organization',
|
|
153
|
+
'@id': this.router.url('/#organization'),
|
|
154
|
+
name: this.app.identity.author.name,
|
|
155
|
+
url: this.app.identity.author.url,
|
|
156
|
+
logo: {
|
|
157
|
+
'@type': 'ImageObject',
|
|
158
|
+
'@id': this.router.url('/#logo'),
|
|
159
|
+
url: this.router.url('/public/brand/1024.png'),
|
|
160
|
+
width: '1024px',
|
|
161
|
+
height: '1024px',
|
|
162
|
+
caption: this.app.identity.name,
|
|
163
|
+
},
|
|
164
|
+
sameAs: [],
|
|
167
165
|
},
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
166
|
+
{
|
|
167
|
+
'@type': 'WebSite',
|
|
168
|
+
'@id': this.router.url('/#website'),
|
|
169
|
+
url: this.router.url('/'),
|
|
170
|
+
name: this.app.identity.name,
|
|
171
|
+
description: this.app.identity.description,
|
|
172
|
+
publisher: { '@id': this.router.url('/#organization') },
|
|
173
|
+
inLanguage: this.app.identity.locale,
|
|
174
|
+
potentialAction: [],
|
|
175
|
+
|
|
176
|
+
...(this.app.identity.web.jsonld || {}),
|
|
177
177
|
},
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
{
|
|
179
|
+
'@type': 'WebPage',
|
|
180
|
+
'@id': this.url,
|
|
181
|
+
url: this.url,
|
|
180
182
|
|
|
181
|
-
|
|
182
|
-
}, {
|
|
183
|
-
'@type': "WebPage",
|
|
184
|
-
'@id': this.url,
|
|
185
|
-
url: this.url,
|
|
183
|
+
isPartOf: { '@id': this.router.url('/#website') },
|
|
186
184
|
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
name: this.title,
|
|
186
|
+
description: this.description,
|
|
187
|
+
inLanguage: this.app.identity.locale,
|
|
189
188
|
},
|
|
190
|
-
|
|
191
|
-
name: this.title,
|
|
192
|
-
description: this.description,
|
|
193
|
-
inLanguage: this.app.identity.locale,
|
|
194
|
-
});
|
|
189
|
+
);
|
|
195
190
|
}
|
|
196
|
-
}
|
|
191
|
+
}
|
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
5
|
// Core
|
|
6
|
-
import type { Application } from '@server/app';
|
|
7
|
-
import Service, {
|
|
6
|
+
import type { Application } from '@server/app/index';
|
|
7
|
+
import Service, { TSetupConfig } from '@server/app/service';
|
|
8
8
|
|
|
9
9
|
// Specific
|
|
10
10
|
import type { default as Router } from '.';
|
|
11
11
|
import type ServerRequest from './request';
|
|
12
|
-
import type RequestService from './request/service';
|
|
13
12
|
import type { TAnyRouter } from '.';
|
|
14
13
|
|
|
15
|
-
export type AnyRouterService = RouterService<any, TAnyRouter>;
|
|
14
|
+
export type AnyRouterService = RouterService<any, TAnyRouter, object | null>;
|
|
16
15
|
|
|
17
|
-
export type TRouterServiceArgs = [
|
|
18
|
-
getConfig:
|
|
19
|
-
app:
|
|
16
|
+
export type TRouterServiceArgs<TConfig extends {} = {}, TRouter extends TAnyRouter = TAnyRouter> = [
|
|
17
|
+
getConfig: TSetupConfig<TConfig> | null | undefined,
|
|
18
|
+
app: TRouter['app'],
|
|
20
19
|
];
|
|
21
20
|
|
|
22
21
|
/*----------------------------------
|
|
@@ -24,13 +23,12 @@ export type TRouterServiceArgs = [
|
|
|
24
23
|
----------------------------------*/
|
|
25
24
|
export default abstract class RouterService<
|
|
26
25
|
TConfig extends {},
|
|
27
|
-
TRouter extends TAnyRouter
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
public constructor(
|
|
31
|
-
super(app, config, app);
|
|
26
|
+
TRouter extends TAnyRouter = TAnyRouter,
|
|
27
|
+
TRequestService extends object | null = object | null,
|
|
28
|
+
> extends Service<TConfig, {}, TRouter['app'], TRouter> {
|
|
29
|
+
public constructor(...[config, app]: TRouterServiceArgs<TConfig, TRouter>) {
|
|
30
|
+
super(app as TRouter['app'] & TRouter, config, app);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
public abstract requestService(
|
|
35
|
-
|
|
36
|
-
}
|
|
33
|
+
public abstract requestService(request: ServerRequest<TRouter>): TRequestService;
|
|
34
|
+
}
|
|
@@ -3,42 +3,33 @@
|
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
5
|
// Core
|
|
6
|
-
import type { Application } from '@server/app';
|
|
6
|
+
import type { Application } from '@server/app/index';
|
|
7
7
|
|
|
8
8
|
// Specific
|
|
9
|
-
import {
|
|
10
|
-
import Validator, { TValidatorOptions } from '@server/services/router/request/validation/validator';
|
|
9
|
+
import { schema, type TRichTextValidatorOptions } from '@server/services/router/request/validation/zod';
|
|
11
10
|
|
|
12
11
|
/*----------------------------------
|
|
13
12
|
- TYPES
|
|
14
13
|
----------------------------------*/
|
|
15
14
|
|
|
15
|
+
export type TFileValidator = boolean;
|
|
16
|
+
export type TValidatorOptions<TValue> = { default?: TValue; optional?: boolean };
|
|
17
|
+
|
|
18
|
+
type TCompatValidator<TValue> = {
|
|
19
|
+
validate: (value: unknown, options?: unknown, path?: string[]) => TValue;
|
|
20
|
+
};
|
|
16
21
|
|
|
17
22
|
/*----------------------------------
|
|
18
23
|
- SERVICE
|
|
19
24
|
----------------------------------*/
|
|
20
|
-
export default class ServerSchemaValidator
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
super();
|
|
25
|
+
export default class ServerSchemaValidator {
|
|
26
|
+
public constructor(public app: Application) {
|
|
27
|
+
void app;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
public richText = (
|
|
27
|
-
attachements?: TFileValidator
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Uploads are done in the business code since the process is specific to every case:
|
|
34
|
-
// - ID in the destination directory
|
|
35
|
-
// - Cleanup before upload
|
|
36
|
-
|
|
37
|
-
return val;
|
|
38
|
-
|
|
39
|
-
}, {
|
|
40
|
-
//defaut: new Date,
|
|
41
|
-
...opts,
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
}
|
|
30
|
+
public richText = (
|
|
31
|
+
opts: TValidatorOptions<string> & { attachements?: TFileValidator } = {},
|
|
32
|
+
): TCompatValidator<string> => ({
|
|
33
|
+
validate: (value: unknown) => schema.richText(opts as TRichTextValidatorOptions).parse(value) as string,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import zod from 'zod';
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
// Core
|
|
9
|
-
import {
|
|
10
|
-
default as Router, TServerRouter, Request as ServerRequest
|
|
11
|
-
} from '@server/services/router';
|
|
9
|
+
import { TServerRouter, Request as ServerRequest } from '@server/services/router';
|
|
12
10
|
|
|
13
11
|
// Ap
|
|
14
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
schema,
|
|
14
|
+
toValidationSchema,
|
|
15
|
+
type TValidationSchema,
|
|
16
|
+
type TValidationShape,
|
|
17
|
+
} from '@server/services/router/request/validation/zod';
|
|
15
18
|
|
|
16
19
|
/*----------------------------------
|
|
17
20
|
- SERVICE CONFIG
|
|
@@ -19,39 +22,23 @@ import { preprocessSchema, schema } from '@server/services/router/request/valida
|
|
|
19
22
|
|
|
20
23
|
const LogPrefix = `[router][validation]`;
|
|
21
24
|
|
|
22
|
-
export type TConfig = {
|
|
23
|
-
debug?: boolean
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type TValidationSchema = zod.ZodTypeAny;
|
|
27
|
-
type TValidationShape = zod.ZodRawShape;
|
|
28
|
-
|
|
29
|
-
const isZodSchema = (fields: unknown): fields is TValidationSchema => {
|
|
30
|
-
return (
|
|
31
|
-
typeof fields === 'object'
|
|
32
|
-
&& fields !== null
|
|
33
|
-
&& 'safeParse' in fields
|
|
34
|
-
&& typeof (fields as TValidationSchema).safeParse === 'function'
|
|
35
|
-
);
|
|
36
|
-
}
|
|
25
|
+
export type TConfig = { debug?: boolean };
|
|
37
26
|
|
|
38
27
|
/*----------------------------------
|
|
39
28
|
- SERVICE
|
|
40
29
|
----------------------------------*/
|
|
41
|
-
export default(
|
|
42
|
-
request: ServerRequest<
|
|
30
|
+
export default (
|
|
31
|
+
request: ServerRequest<TServerRouter>,
|
|
43
32
|
config: TConfig,
|
|
44
33
|
router = request.router,
|
|
45
|
-
|
|
34
|
+
_app = router.app,
|
|
46
35
|
) => {
|
|
36
|
+
function validate<TSchema extends TValidationSchema>(fields: TSchema): zod.output<TSchema>;
|
|
37
|
+
function validate<TShape extends TValidationShape>(fields: TShape): zod.output<zod.ZodObject<TShape>>;
|
|
38
|
+
function validate(fields: TValidationSchema | TValidationShape) {
|
|
39
|
+
config.debug && console.log(LogPrefix, 'Validate request data:', request.data);
|
|
47
40
|
|
|
48
|
-
|
|
49
|
-
function validate<TShape extends TValidationShape>( fields: TShape ): zod.output<zod.ZodObject<TShape>>;
|
|
50
|
-
function validate( fields: TValidationSchema | TValidationShape ) {
|
|
51
|
-
|
|
52
|
-
config.debug && console.log(LogPrefix, "Validate request data:", request.data);
|
|
53
|
-
|
|
54
|
-
const validationSchema = isZodSchema(fields) ? fields : zod.object(fields);
|
|
41
|
+
const validationSchema = toValidationSchema(fields);
|
|
55
42
|
|
|
56
43
|
//const preprocessedSchema = preprocessSchema(validationSchema);
|
|
57
44
|
|
|
@@ -59,9 +46,8 @@ export default(
|
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
return {
|
|
62
|
-
|
|
63
49
|
...schema,
|
|
64
50
|
|
|
65
51
|
validate,
|
|
66
|
-
}
|
|
67
|
-
}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
5
|
// Core
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
RouterService,
|
|
6
|
+
import {
|
|
7
|
+
Request as ServerRequest,
|
|
8
|
+
RouterService,
|
|
9
|
+
TAnyRouter,
|
|
9
10
|
} from '@server/services/router';
|
|
10
11
|
|
|
11
12
|
import makeRequestValidators from '../request';
|
|
@@ -14,15 +15,11 @@ import makeRequestValidators from '../request';
|
|
|
14
15
|
- TYPES
|
|
15
16
|
----------------------------------*/
|
|
16
17
|
|
|
17
|
-
|
|
18
18
|
/*----------------------------------
|
|
19
19
|
- SERVICE
|
|
20
20
|
----------------------------------*/
|
|
21
|
-
export default class SchemaRouterService<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
public requestService( request: ServerRequest ) {
|
|
26
|
-
return makeRequestValidators( request, this.config );
|
|
21
|
+
export default class SchemaRouterService<TUser extends {} = {}> extends RouterService<{}, TAnyRouter> {
|
|
22
|
+
public requestService(request: ServerRequest) {
|
|
23
|
+
return makeRequestValidators(request, this.config);
|
|
27
24
|
}
|
|
28
|
-
}
|
|
25
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import crypto, { Encoding } from 'crypto';
|
|
7
7
|
|
|
8
8
|
// Core
|
|
9
|
-
import type { Application } from '@server/app';
|
|
9
|
+
import type { Application } from '@server/app/index';
|
|
10
10
|
import Service from '@server/app/service';
|
|
11
11
|
import { Forbidden } from '@common/errors';
|
|
12
12
|
|
|
@@ -15,45 +15,33 @@ import { Forbidden } from '@common/errors';
|
|
|
15
15
|
----------------------------------*/
|
|
16
16
|
|
|
17
17
|
export type Config = {
|
|
18
|
-
debug?: boolean
|
|
18
|
+
debug?: boolean;
|
|
19
19
|
// Initialisation vector
|
|
20
20
|
// Generate one here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx
|
|
21
|
-
iv: string
|
|
21
|
+
iv: string;
|
|
22
22
|
// Define usage-specific keys
|
|
23
23
|
// You can also generate one via the link upper
|
|
24
|
-
keys: {[keyName: string]: string}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type Hooks = {
|
|
24
|
+
keys: { [keyName: string]: string };
|
|
25
|
+
};
|
|
28
26
|
|
|
29
|
-
}
|
|
27
|
+
export type Hooks = {};
|
|
30
28
|
|
|
31
|
-
export type Services = {
|
|
32
|
-
|
|
33
|
-
}
|
|
29
|
+
export type Services = {};
|
|
34
30
|
|
|
35
31
|
/*----------------------------------
|
|
36
32
|
- TYPES
|
|
37
33
|
----------------------------------*/
|
|
38
34
|
|
|
39
|
-
type TEncryptOptions = {
|
|
40
|
-
encoding: Encoding
|
|
41
|
-
}
|
|
35
|
+
type TEncryptOptions = { encoding: Encoding };
|
|
42
36
|
|
|
43
|
-
type TDecryptOptions = {
|
|
44
|
-
encoding: Encoding
|
|
45
|
-
}
|
|
37
|
+
type TDecryptOptions = { encoding: Encoding };
|
|
46
38
|
|
|
47
39
|
/*----------------------------------
|
|
48
40
|
- SERVICE
|
|
49
41
|
----------------------------------*/
|
|
50
42
|
export default class AES<TConfig extends Config = Config> extends Service<TConfig, Hooks, Application, Application> {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
encoding: 'base64url'
|
|
54
|
-
}) {
|
|
55
|
-
|
|
56
|
-
const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
|
|
43
|
+
public encrypt(keyName: keyof TConfig['keys'], data: any, options: TEncryptOptions = { encoding: 'base64url' }) {
|
|
44
|
+
const encKey = this.config.keys[keyName as keyof typeof this.config.keys];
|
|
57
45
|
|
|
58
46
|
data = JSON.stringify(data);
|
|
59
47
|
|
|
@@ -61,25 +49,17 @@ export default class AES<TConfig extends Config = Config> extends Service<TConfi
|
|
|
61
49
|
let encrypted = cipher.update(data, 'utf8', options.encoding);
|
|
62
50
|
encrypted += cipher.final(options.encoding);
|
|
63
51
|
return encrypted;
|
|
64
|
-
|
|
65
52
|
}
|
|
66
53
|
|
|
67
|
-
public decrypt(
|
|
68
|
-
|
|
69
|
-
}) {
|
|
70
|
-
|
|
71
|
-
const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
|
|
54
|
+
public decrypt(keyName: keyof TConfig['keys'], data: string, options: TDecryptOptions = { encoding: 'base64url' }) {
|
|
55
|
+
const encKey = this.config.keys[keyName as keyof typeof this.config.keys];
|
|
72
56
|
|
|
73
57
|
try {
|
|
74
|
-
|
|
75
58
|
let decipher = crypto.createDecipheriv('aes-256-cbc', encKey, this.config.iv);
|
|
76
59
|
let decrypted = decipher.update(data, options.encoding, 'utf8');
|
|
77
60
|
return JSON.parse(decrypted + decipher.final('utf8'));
|
|
78
|
-
|
|
79
61
|
} catch (error) {
|
|
80
|
-
|
|
81
|
-
throw new Forbidden("Invalid token.");
|
|
82
|
-
|
|
62
|
+
throw new Forbidden('Invalid token.');
|
|
83
63
|
}
|
|
84
64
|
}
|
|
85
|
-
}
|
|
65
|
+
}
|