proteum 1.0.0 → 1.0.2
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/cli/app/config.ts +54 -0
- package/cli/app/index.ts +195 -0
- package/cli/bin.js +35 -0
- package/cli/commands/build.ts +34 -0
- package/cli/commands/deploy/app.ts +29 -0
- package/cli/commands/deploy/web.ts +60 -0
- package/cli/commands/dev.ts +109 -0
- package/cli/commands/init.ts +85 -0
- package/cli/compiler/client/identite.ts +72 -0
- package/cli/compiler/client/index.ts +335 -0
- package/cli/compiler/common/babel/index.ts +170 -0
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +586 -0
- package/cli/compiler/common/babel/routes/imports.ts +127 -0
- package/cli/compiler/common/babel/routes/routes.ts +1130 -0
- package/cli/compiler/common/files/autres.ts +39 -0
- package/cli/compiler/common/files/images.ts +42 -0
- package/cli/compiler/common/files/style.ts +80 -0
- package/cli/compiler/common/index.ts +160 -0
- package/cli/compiler/index.ts +564 -0
- package/cli/compiler/server/index.ts +211 -0
- package/cli/index.ts +189 -0
- package/cli/paths.ts +165 -0
- package/cli/print.ts +12 -0
- package/cli/tsconfig.json +42 -0
- package/cli/utils/index.ts +22 -0
- package/cli/utils/keyboard.ts +78 -0
- package/client/app/index.ts +2 -0
- package/client/components/Dialog/Manager.tsx +3 -49
- package/client/components/Dialog/index.less +3 -1
- package/client/components/index.ts +1 -2
- package/client/services/router/index.tsx +6 -16
- package/common/errors/index.tsx +12 -31
- package/doc/TODO.md +1 -1
- package/package.json +58 -20
- package/server/app/container/console/index.ts +1 -1
- package/server/services/auth/index.ts +62 -27
- package/server/services/auth/router/request.ts +17 -6
- package/server/services/router/http/index.ts +1 -1
- package/server/services/router/response/index.ts +1 -1
- package/server/services/schema/request.ts +28 -10
- package/tsconfig.common.json +2 -1
- package/changelog.md +0 -5
- package/client/components/Button.tsx +0 -298
- package/client/components/Dialog/card.tsx +0 -208
- package/client/data/input.ts +0 -32
- package/client/pages/bug.tsx.old +0 -60
- package/templates/composant.tsx +0 -40
- package/templates/form.ts +0 -30
- package/templates/modal.tsx +0 -47
- package/templates/modele.ts +0 -56
- package/templates/page.tsx +0 -74
- package/templates/route.ts +0 -43
- package/templates/service.ts +0 -75
- package/vscode/copyimportationpath/.eslintrc.json +0 -24
- package/vscode/copyimportationpath/.vscodeignore +0 -12
- package/vscode/copyimportationpath/CHANGELOG.md +0 -9
- package/vscode/copyimportationpath/README.md +0 -3
- package/vscode/copyimportationpath/copyimportationpath-0.0.1.vsix +0 -0
- package/vscode/copyimportationpath/out/extension.js +0 -206
- package/vscode/copyimportationpath/out/extension.js.map +0 -1
- package/vscode/copyimportationpath/package-lock.json +0 -4536
- package/vscode/copyimportationpath/package.json +0 -86
- package/vscode/copyimportationpath/src/extension.ts +0 -300
- package/vscode/copyimportationpath/tsconfig.json +0 -22
- package/vscode/copyimportationpath/vsc-extension-quickstart.md +0 -42
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// npm
|
|
6
|
+
import readline, { Key } from 'readline';
|
|
7
|
+
|
|
8
|
+
/*----------------------------------
|
|
9
|
+
- TYPES
|
|
10
|
+
----------------------------------*/
|
|
11
|
+
|
|
12
|
+
type TKeyboardCommand = {
|
|
13
|
+
remove?: boolean,
|
|
14
|
+
run: (str: string, chunk: string, key: Key) => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/*----------------------------------
|
|
18
|
+
- METHODS
|
|
19
|
+
----------------------------------*/
|
|
20
|
+
class KeyboardCommands {
|
|
21
|
+
|
|
22
|
+
private commands: { [input: string]: TKeyboardCommand } = {}
|
|
23
|
+
|
|
24
|
+
public constructor() {
|
|
25
|
+
this.listen();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private listen() {
|
|
29
|
+
|
|
30
|
+
readline.emitKeypressEvents(process.stdin);
|
|
31
|
+
process.stdin.setRawMode(true);
|
|
32
|
+
process.stdin.on('keypress', async (chunk: string, key: Key) => {
|
|
33
|
+
|
|
34
|
+
let str = key.name;
|
|
35
|
+
if (!str) return;
|
|
36
|
+
if (str === 'return') str = 'enter';
|
|
37
|
+
|
|
38
|
+
if (key.ctrl) str = 'ctrl+' + str;
|
|
39
|
+
if (key.shift) str = 'shift+' + str;
|
|
40
|
+
if (key.meta) str = 'meta+' + str;
|
|
41
|
+
|
|
42
|
+
const kCommand = this.commands[str] || this.commands.fallback;
|
|
43
|
+
if (kCommand) {
|
|
44
|
+
|
|
45
|
+
kCommand.run(str, chunk, key);
|
|
46
|
+
|
|
47
|
+
if (kCommand.remove)
|
|
48
|
+
delete this.commands[str];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (str === 'ctrl+c') {
|
|
52
|
+
|
|
53
|
+
console.log(`Exiting ...`);
|
|
54
|
+
process.exit(0);
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
public input(str: string, run: TKeyboardCommand["run"], options: Omit<TKeyboardCommand, 'run'> = {}) {
|
|
64
|
+
this.commands[str] = { run, ...options }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public waitForInput(str: string): Promise<void> {
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
this.commands[str] = {
|
|
70
|
+
run: () => resolve(),
|
|
71
|
+
remove: true
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default new KeyboardCommands
|
package/client/app/index.ts
CHANGED
|
@@ -120,6 +120,8 @@ export default abstract class Application {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
public abstract handleError( error: CoreError | Error );
|
|
123
|
+
|
|
124
|
+
public abstract handleUpdate(): void;
|
|
123
125
|
|
|
124
126
|
// TODO: move on app side
|
|
125
127
|
public reportBug = (infos: TBugReportInfos) => fetch('/feedback/bug/ui', {
|
|
@@ -12,8 +12,6 @@ import { blurable, deepContains, focusContent } from '@client/utils/dom';
|
|
|
12
12
|
|
|
13
13
|
// Specific
|
|
14
14
|
import type Application from '../../app';
|
|
15
|
-
import Card, { Props as CardInfos } from './card';
|
|
16
|
-
import Button from '../Button';
|
|
17
15
|
|
|
18
16
|
/*----------------------------------
|
|
19
17
|
- TYPES: IMPORTATIONS
|
|
@@ -67,8 +65,6 @@ type DialogActions = {
|
|
|
67
65
|
|
|
68
66
|
show: (...args: TDialogShowArgs ) => TDialogControls,
|
|
69
67
|
|
|
70
|
-
confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No') => TDialogControls,
|
|
71
|
-
|
|
72
68
|
loading: (title: string) => TDialogControls,
|
|
73
69
|
|
|
74
70
|
info: (...[title, content, boutons, options]: TToastShortcutArgs) => TDialogControls,
|
|
@@ -137,34 +133,11 @@ export const createDialog = (app: Application, isToast: boolean): DialogActions
|
|
|
137
133
|
content: Content
|
|
138
134
|
}
|
|
139
135
|
}
|
|
140
|
-
|
|
141
|
-
// modal.show({ title: 'supprimer', content: <>...</> })
|
|
142
|
-
if (Content.constructor === Object) {
|
|
143
|
-
|
|
144
|
-
const { content: CardContent, data = {}, ...propsToast } = Content as TOptsToast;
|
|
145
|
-
|
|
146
|
-
let cardContent: ComponentChild;
|
|
147
|
-
if (typeof CardContent === 'function') {
|
|
148
|
-
cardContent = <CardContent {...propsRendu} {...data} />
|
|
149
|
-
propsToast.boutons = null; // Component content = advanced content = should include buttons
|
|
150
|
-
} else {
|
|
151
|
-
cardContent = CardContent;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
render = (
|
|
155
|
-
<Card {...propsRendu} {...propsToast} isToast={isToast}>
|
|
156
|
-
{cardContent}
|
|
157
|
-
</Card>
|
|
158
|
-
)
|
|
159
|
-
|
|
160
136
|
// modal.show( ToastSupprimer )
|
|
161
137
|
// -> Content is a component rendering a Card
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<Content {...propsRendu} isToast={isToast} />
|
|
166
|
-
)
|
|
167
|
-
}
|
|
138
|
+
render = (
|
|
139
|
+
<Content {...propsRendu} isToast={isToast} />
|
|
140
|
+
)
|
|
168
141
|
|
|
169
142
|
// Chargeur de données
|
|
170
143
|
/*if (('data' in ComposantCharge) && typeof ComposantCharge.data === 'function') {
|
|
@@ -202,25 +175,6 @@ export const createDialog = (app: Application, isToast: boolean): DialogActions
|
|
|
202
175
|
setToasts: undefined as unknown as DialogActions["setToasts"],
|
|
203
176
|
setModals: undefined as unknown as DialogActions["setModals"],
|
|
204
177
|
|
|
205
|
-
confirm: (title: string, content: string | ComponentChild, defaultBtn: 'Yes'|'No' = 'No') => show<boolean>(({ close }) => (
|
|
206
|
-
<div class="card col">
|
|
207
|
-
<header>
|
|
208
|
-
<h2>{title}</h2>
|
|
209
|
-
</header>
|
|
210
|
-
{typeof content === 'string' ? <p>{content}</p> : content}
|
|
211
|
-
<footer class="row fill">
|
|
212
|
-
<Button type={defaultBtn === 'Yes' ? 'primary' : undefined}
|
|
213
|
-
onClick={() => close(true)}>
|
|
214
|
-
Yes
|
|
215
|
-
</Button>
|
|
216
|
-
<Button type={defaultBtn === 'No' ? 'primary' : undefined}
|
|
217
|
-
onClick={() => close(false)}>
|
|
218
|
-
No
|
|
219
|
-
</Button>
|
|
220
|
-
</footer>
|
|
221
|
-
</div>
|
|
222
|
-
)),
|
|
223
|
-
|
|
224
178
|
loading: (title: string) => show({
|
|
225
179
|
title: title,
|
|
226
180
|
type: 'loading'
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { Link } from '../services/router/components/Link';
|
|
2
|
-
export { default as Button } from './Button';
|
|
1
|
+
export { Link } from '../services/router/components/Link';
|
|
@@ -10,7 +10,8 @@ import ReactDOM from 'react-dom';
|
|
|
10
10
|
import type {
|
|
11
11
|
default as ServerRouter,
|
|
12
12
|
Request as ServerRequest,
|
|
13
|
-
Response as ServerResponse
|
|
13
|
+
Response as ServerResponse,
|
|
14
|
+
TAnyRouter
|
|
14
15
|
} from '@server/services/router';
|
|
15
16
|
import type { TBasicSSrData } from '@server/services/router/response';
|
|
16
17
|
|
|
@@ -23,7 +24,6 @@ import { getLayout } from '@common/router/layouts';
|
|
|
23
24
|
import { getRegisterPageArgs, buildRegex } from '@common/router/register';
|
|
24
25
|
import { TFetcherList } from '@common/router/request/api';
|
|
25
26
|
import type { TFrontRenderer } from '@common/router/response/page';
|
|
26
|
-
import Button from '../../components/Button';
|
|
27
27
|
|
|
28
28
|
import App from '@client/app/component';
|
|
29
29
|
import type ClientApplication from '@client/app';
|
|
@@ -56,11 +56,11 @@ const LogPrefix = '[router]'
|
|
|
56
56
|
// Client router can handle Client requests AND Server requests (for pages only)
|
|
57
57
|
export type { default as ClientResponse, TRouterContext } from "./response";
|
|
58
58
|
|
|
59
|
-
export type Router = ClientRouter |
|
|
59
|
+
export type Router = ClientRouter | TAnyRouter;
|
|
60
60
|
|
|
61
|
-
export type Request = ClientRequest<ClientRouter> | ServerRequest<
|
|
61
|
+
export type Request = ClientRequest<ClientRouter> | ServerRequest<TAnyRouter>;
|
|
62
62
|
|
|
63
|
-
export type Response = ClientResponse<ClientRouter> | ServerResponse<
|
|
63
|
+
export type Response = ClientResponse<ClientRouter> | ServerResponse<TAnyRouter>;
|
|
64
64
|
|
|
65
65
|
/*----------------------------------
|
|
66
66
|
- TYPES: ROUTES LOADING
|
|
@@ -360,17 +360,7 @@ export default class ClientRouter<
|
|
|
360
360
|
} catch (e) {
|
|
361
361
|
console.error(`Failed to fetch the route ${route.chunk}`, e);
|
|
362
362
|
try {
|
|
363
|
-
this.
|
|
364
|
-
<div class="card col bg white w-3">
|
|
365
|
-
<h2>New Update Available!</h2>
|
|
366
|
-
<p>
|
|
367
|
-
A new version of the website is available. Please refresh the page to continue.
|
|
368
|
-
</p>
|
|
369
|
-
<Button type="primary" onClick={() => window.location.reload()}>
|
|
370
|
-
Reload
|
|
371
|
-
</Button>
|
|
372
|
-
</div>
|
|
373
|
-
));
|
|
363
|
+
this.app.handleUpdate();
|
|
374
364
|
} catch (error) {}
|
|
375
365
|
throw new Error("A new version of the website is available. Please refresh the page.");
|
|
376
366
|
}
|
package/common/errors/index.tsx
CHANGED
|
@@ -35,27 +35,6 @@ type TErrorDetails = {
|
|
|
35
35
|
origin?: string,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/*----------------------------------
|
|
39
|
-
- TYPES: AUTH REQUIRED FEATURE
|
|
40
|
-
----------------------------------*/
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Global, augmentable feature catalog used to constrain the `feature` argument
|
|
44
|
-
* of `AuthRequired`.
|
|
45
|
-
*
|
|
46
|
-
* Default behavior (no augmentation): `feature` stays a free-form string.
|
|
47
|
-
* App behavior (augmentation provided by the host app): `feature` becomes a
|
|
48
|
-
* curated union of feature keys.
|
|
49
|
-
*/
|
|
50
|
-
declare global {
|
|
51
|
-
interface TAuthRequiredFeatureCatalog {}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
type TAuthRequiredFeatureKey = Extract<keyof TAuthRequiredFeatureCatalog, string>;
|
|
55
|
-
type TAuthRequiredFeature = [TAuthRequiredFeatureKey] extends [never]
|
|
56
|
-
? string
|
|
57
|
-
: TAuthRequiredFeatureKey;
|
|
58
|
-
|
|
59
38
|
/*----------------------------------
|
|
60
39
|
- TYPES: BUG REPORT
|
|
61
40
|
----------------------------------*/
|
|
@@ -179,46 +158,48 @@ export class InputErrorSchema extends CoreError {
|
|
|
179
158
|
}
|
|
180
159
|
}
|
|
181
160
|
|
|
182
|
-
export class AuthRequired extends CoreError {
|
|
161
|
+
export class AuthRequired<FeatureKeys extends string> extends CoreError {
|
|
183
162
|
public http = 401;
|
|
184
163
|
public title = "Authentication Required";
|
|
185
164
|
public static msgDefaut = "Please Login to Continue.";
|
|
186
165
|
|
|
187
|
-
public constructor(message: string, feature?: TAuthRequiredFeature);
|
|
188
|
-
public constructor(message: string, motivation: string | undefined, details: TErrorDetails | undefined);
|
|
189
166
|
public constructor(
|
|
190
167
|
message: string,
|
|
191
|
-
public feature
|
|
168
|
+
public feature: FeatureKeys,
|
|
169
|
+
public action: string,
|
|
192
170
|
details?: TErrorDetails
|
|
193
171
|
) {
|
|
194
172
|
super(message, details);
|
|
195
173
|
}
|
|
196
174
|
|
|
197
|
-
public json(): TJsonError & { feature
|
|
175
|
+
public json(): TJsonError & { feature: string, action: string } {
|
|
198
176
|
return {
|
|
199
177
|
...super.json(),
|
|
200
178
|
feature: this.feature,
|
|
179
|
+
action: this.action,
|
|
201
180
|
}
|
|
202
181
|
}
|
|
203
182
|
}
|
|
204
183
|
|
|
205
|
-
export class UpgradeRequired extends CoreError {
|
|
184
|
+
export class UpgradeRequired<FeatureKeys extends string> extends CoreError {
|
|
206
185
|
public http = 402;
|
|
207
186
|
public title = "Upgrade Required";
|
|
208
187
|
public static msgDefaut = "Please Upgrade to Continue.";
|
|
209
188
|
|
|
210
189
|
public constructor(
|
|
211
190
|
message: string,
|
|
212
|
-
public feature:
|
|
191
|
+
public feature: FeatureKeys,
|
|
192
|
+
public action: string,
|
|
213
193
|
details?: TErrorDetails
|
|
214
194
|
) {
|
|
215
195
|
super(message, details);
|
|
216
196
|
}
|
|
217
197
|
|
|
218
|
-
public json(): TJsonError & { feature: string } {
|
|
198
|
+
public json(): TJsonError & { feature: string, action: string } {
|
|
219
199
|
return {
|
|
220
200
|
...super.json(),
|
|
221
201
|
feature: this.feature,
|
|
202
|
+
action: this.action,
|
|
222
203
|
}
|
|
223
204
|
}
|
|
224
205
|
}
|
|
@@ -308,9 +289,9 @@ export const fromJson = ({ code, message, ...details }: TJsonError) => {
|
|
|
308
289
|
else
|
|
309
290
|
return new InputError( message, details );
|
|
310
291
|
|
|
311
|
-
case 401: return new AuthRequired( message,
|
|
292
|
+
case 401: return new AuthRequired( message, details["feature"], details["action"], details );
|
|
312
293
|
|
|
313
|
-
case 402: return new UpgradeRequired( message, details
|
|
294
|
+
case 402: return new UpgradeRequired( message, details["feature"], details["action"], details );
|
|
314
295
|
|
|
315
296
|
case 403: return new Forbidden( message, details );
|
|
316
297
|
|
package/doc/TODO.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proteum",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/proteum.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -12,74 +12,105 @@
|
|
|
12
12
|
"keywords": [
|
|
13
13
|
"framework"
|
|
14
14
|
],
|
|
15
|
+
"bin": {
|
|
16
|
+
"proteum": "cli/bin.js"
|
|
17
|
+
},
|
|
15
18
|
"dependencies": {
|
|
16
|
-
"@
|
|
17
|
-
"@
|
|
18
|
-
"@
|
|
19
|
+
"@babel/cli": "^7.15.4",
|
|
20
|
+
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
|
21
|
+
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
22
|
+
"@babel/plugin-proposal-private-methods": "^7.14.5",
|
|
23
|
+
"@babel/plugin-proposal-private-property-in-object": "^7.15.4",
|
|
24
|
+
"@babel/plugin-transform-react-constant-elements": "^7.14.5",
|
|
25
|
+
"@babel/preset-env": "^7.15.6",
|
|
26
|
+
"@babel/preset-react": "^7.14.5",
|
|
27
|
+
"@babel/preset-typescript": "^7.15.0",
|
|
19
28
|
"@lexical/react": "^0.18.0",
|
|
29
|
+
"@prefresh/webpack": "^3.3.2",
|
|
20
30
|
"@prisma/client": "^6.5.0",
|
|
31
|
+
"@tailwindcss/postcss": "^4.1.17",
|
|
21
32
|
"accepts": "^1.3.7",
|
|
22
|
-
"activity-detector": "^3.0.0",
|
|
23
33
|
"ansi-to-html": "^0.7.1",
|
|
24
|
-
"
|
|
34
|
+
"autoprefixer": "^10.4.21",
|
|
25
35
|
"aws-sdk": "^2.1415.0",
|
|
36
|
+
"babel-loader": "^10.0.0",
|
|
37
|
+
"babel-plugin-glob-import": "^0.0.9-1",
|
|
38
|
+
"babel-plugin-transform-imports": "^2.0.0",
|
|
39
|
+
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
40
|
+
"babel-plugin-transform-remove-console": "^6.9.4",
|
|
26
41
|
"bowser": "^2.11.0",
|
|
27
|
-
"
|
|
42
|
+
"brotli-webpack-plugin": "^1.1.0",
|
|
43
|
+
"browser-sync": "^2.27.5",
|
|
28
44
|
"cli-highlight": "^2.1.11",
|
|
29
45
|
"compression": "^1.7.4",
|
|
46
|
+
"compression-webpack-plugin": "^8.0.1",
|
|
30
47
|
"cookie-parser": "^1.4.5",
|
|
31
48
|
"core-js": "^3.18.1",
|
|
32
49
|
"cors": "^2.8.5",
|
|
33
50
|
"cron-parser": "^4.0.0",
|
|
51
|
+
"css-loader": "^6.2.0",
|
|
52
|
+
"css-minimizer-webpack-plugin": "^7.0.4",
|
|
34
53
|
"dayjs": "^1.11.5",
|
|
35
|
-
"deep-extend": "^0.6.0",
|
|
36
54
|
"dottie": "^2.0.2",
|
|
37
55
|
"escape-regexp": "^0.0.1",
|
|
38
56
|
"express": "^4.17.1",
|
|
39
57
|
"express-csp-header": "^5.0.0",
|
|
40
58
|
"express-fileupload": "^1.2.1",
|
|
41
59
|
"fast-safe-stringify": "^2.1.1",
|
|
42
|
-
"
|
|
43
|
-
"formattor": "^0.0.2",
|
|
60
|
+
"favicons": "^7.2.0",
|
|
44
61
|
"fs-extra": "^10.1.0",
|
|
45
62
|
"got": "^11.8.3",
|
|
46
|
-
"handlebars": "^4.7.7",
|
|
47
63
|
"helmet": "^4.6.0",
|
|
48
64
|
"history": "^5.0.1",
|
|
49
65
|
"hpp": "^0.2.3",
|
|
50
66
|
"human-interval": "^2.0.1",
|
|
67
|
+
"image-minimizer-webpack-plugin": "^4.1.4",
|
|
68
|
+
"imagemin": "^9.0.1",
|
|
69
|
+
"imagemin-svgo": "^10.0.0",
|
|
70
|
+
"imagemin-webp": "^6.0.0",
|
|
51
71
|
"intl": "^1.2.5",
|
|
52
72
|
"iso-639-1": "^2.1.9",
|
|
53
|
-
"
|
|
54
|
-
"jsdom": "^25.0.1",
|
|
73
|
+
"json5": "^2.2.0",
|
|
55
74
|
"jsonwebtoken": "^8.5.1",
|
|
75
|
+
"less-loader": "^10.0.1",
|
|
56
76
|
"lexical": "^0.18.0",
|
|
57
77
|
"load-script": "^2.0.0",
|
|
58
78
|
"locale": "^0.1.0",
|
|
59
79
|
"markdown-it": "^13.0.1",
|
|
60
80
|
"md5": "^2.3.0",
|
|
61
81
|
"mime-types": "^2.1.35",
|
|
82
|
+
"mini-css-extract-plugin": "^2.2.2",
|
|
62
83
|
"module-alias": "^2.2.2",
|
|
63
84
|
"mysql2": "^2.3.0",
|
|
85
|
+
"node-cmd": "^5.0.0",
|
|
86
|
+
"null-loader": "^4.0.1",
|
|
64
87
|
"object-sizeof": "^1.6.3",
|
|
65
88
|
"path-to-regexp": "^6.2.0",
|
|
66
|
-
"
|
|
89
|
+
"postcss-loader": "^8.2.0",
|
|
67
90
|
"preact": "^10.27.1",
|
|
68
91
|
"preact-render-to-string": "^6.6.1",
|
|
69
92
|
"prettier": "^3.3.3",
|
|
70
|
-
"
|
|
71
|
-
"react-
|
|
72
|
-
"react-textarea-autosize": "^8.5.9",
|
|
93
|
+
"prompts": "^2.4.2",
|
|
94
|
+
"react-dev-utils": "^11.0.4",
|
|
73
95
|
"regenerator-runtime": "^0.13.9",
|
|
96
|
+
"replace-once": "^1.0.0",
|
|
74
97
|
"request": "^2.88.2",
|
|
98
|
+
"responsive-loader": "^3.1.2",
|
|
99
|
+
"serialize-javascript": "^6.0.2",
|
|
100
|
+
"sharp": "^0.34.3",
|
|
75
101
|
"slugify": "^1.6.6",
|
|
76
102
|
"source-map-support": "^0.5.21",
|
|
77
|
-
"sql-formatter": "^4.0.2",
|
|
78
103
|
"stopword": "^3.1.1",
|
|
104
|
+
"tailwindcss": "^4.1.17",
|
|
105
|
+
"terser-webpack-plugin": "^5.2.4",
|
|
106
|
+
"ts-alias": "^0.0.7",
|
|
107
|
+
"ts-node": "^10.9.1",
|
|
79
108
|
"tslog": "^4.9.1",
|
|
80
109
|
"uuid": "^8.3.2",
|
|
81
|
-
"uuid-by-string": "^3.0.4",
|
|
82
110
|
"validator": "^13.7.0",
|
|
111
|
+
"webpack": "^5.104.1",
|
|
112
|
+
"webpack-assets-manifest": "^5.0.6",
|
|
113
|
+
"webpack-bundle-analyzer": "^4.4.2",
|
|
83
114
|
"ws": "^8.2.2",
|
|
84
115
|
"yaml": "^1.10.2",
|
|
85
116
|
"yargs-parser": "^21.1.1",
|
|
@@ -88,18 +119,25 @@
|
|
|
88
119
|
"zod": "^4.1.5"
|
|
89
120
|
},
|
|
90
121
|
"devDependencies": {
|
|
122
|
+
"@types/babel__core": "^7.1.16",
|
|
123
|
+
"@types/babel__preset-env": "^7.9.6",
|
|
91
124
|
"@types/cookie": "^0.4.1",
|
|
92
125
|
"@types/express": "^4.17.13",
|
|
126
|
+
"@types/favicons": "^6.2.2",
|
|
93
127
|
"@types/fs-extra": "^9.0.12",
|
|
94
128
|
"@types/markdown-it": "^12.2.3",
|
|
95
129
|
"@types/mime-types": "^2.1.1",
|
|
96
130
|
"@types/node": "^16.9.1",
|
|
97
131
|
"@types/nodemailer": "^6.4.4",
|
|
132
|
+
"@types/pg": "^8.6.1",
|
|
133
|
+
"@types/pg-escape": "^0.2.1",
|
|
134
|
+
"@types/prompts": "^2.0.14",
|
|
98
135
|
"@types/sharp": "^0.31.1",
|
|
99
136
|
"@types/universal-analytics": "^0.4.5",
|
|
100
137
|
"@types/webpack-env": "^1.16.2",
|
|
101
138
|
"@types/ws": "^7.4.7",
|
|
102
139
|
"@types/yargs-parser": "^21.0.0",
|
|
103
|
-
"schema-dts": "^1.1.2"
|
|
140
|
+
"schema-dts": "^1.1.2",
|
|
141
|
+
"speed-measure-webpack-v5-plugin": "^1.5.2"
|
|
104
142
|
}
|
|
105
143
|
}
|
|
@@ -258,7 +258,7 @@ export default class Console {
|
|
|
258
258
|
if (filepath.startsWith( projectRoot ))
|
|
259
259
|
filepath = filepath.substring( projectRoot.length )
|
|
260
260
|
|
|
261
|
-
const frameworkRoot = '/node_modules/
|
|
261
|
+
const frameworkRoot = '/node_modules/proteum/';
|
|
262
262
|
if (filepath.startsWith( frameworkRoot ))
|
|
263
263
|
filepath = '@' + filepath.substring( frameworkRoot.length )
|
|
264
264
|
|
|
@@ -20,10 +20,47 @@ import { InputError, AuthRequired, Forbidden } from '@common/errors';
|
|
|
20
20
|
- TYPES
|
|
21
21
|
----------------------------------*/
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
declare global {
|
|
24
|
+
/**
|
|
25
|
+
* Optional app-level role registry.
|
|
26
|
+
*
|
|
27
|
+
* Apps can add their own roles (keys are role ids):
|
|
28
|
+
* `interface ProteumAuthRoleCatalog { GOD: true }`
|
|
29
|
+
*/
|
|
30
|
+
interface ProteumAuthRoleCatalog {}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* App-level feature catalog consumed by auth permission checks.
|
|
34
|
+
*
|
|
35
|
+
* Apps can augment this interface with their own feature map:
|
|
36
|
+
* `interface ProteumAuthFeatureCatalog extends MyFeatures {}`
|
|
37
|
+
*/
|
|
38
|
+
interface ProteumAuthFeatureCatalog {}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Canonical feature keys union used across app + framework.
|
|
42
|
+
*
|
|
43
|
+
* Notes:
|
|
44
|
+
* - If the app does not define a feature catalog, this defaults to `string`.
|
|
45
|
+
* - Otherwise it becomes the string keys of `ProteumAuthFeatureCatalog`.
|
|
46
|
+
*/
|
|
47
|
+
type FeatureKeys = (
|
|
48
|
+
keyof ProteumAuthFeatureCatalog extends never
|
|
49
|
+
? string
|
|
50
|
+
: Extract<keyof ProteumAuthFeatureCatalog, string>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type TUserRole = (
|
|
55
|
+
typeof UserRoles[number]
|
|
56
|
+
|
|
|
57
|
+
Extract<keyof ProteumAuthRoleCatalog, string>
|
|
58
|
+
);
|
|
24
59
|
|
|
25
60
|
export type THttpRequest = express.Request | http.IncomingMessage;
|
|
26
61
|
|
|
62
|
+
export type TFeatureKey = FeatureKeys;
|
|
63
|
+
|
|
27
64
|
/*----------------------------------
|
|
28
65
|
- CONFIG
|
|
29
66
|
----------------------------------*/
|
|
@@ -167,7 +204,7 @@ export default abstract class AuthService<
|
|
|
167
204
|
return session;
|
|
168
205
|
}
|
|
169
206
|
|
|
170
|
-
public createSession( session: TJwtSession,
|
|
207
|
+
public createSession( session: TJwtSession, request2: TRequest ): string {
|
|
171
208
|
|
|
172
209
|
this.config.debug && console.info(LogPrefix, `Creating new session:`, session);
|
|
173
210
|
|
|
@@ -175,7 +212,7 @@ export default abstract class AuthService<
|
|
|
175
212
|
|
|
176
213
|
this.config.debug && console.info(LogPrefix, `Generated JWT token for session:` + token);
|
|
177
214
|
|
|
178
|
-
|
|
215
|
+
request2.res.cookie('authorization', token, {
|
|
179
216
|
maxAge: this.config.jwt.expiration,
|
|
180
217
|
});
|
|
181
218
|
|
|
@@ -191,30 +228,28 @@ export default abstract class AuthService<
|
|
|
191
228
|
request.res.clearCookie('authorization');
|
|
192
229
|
}
|
|
193
230
|
|
|
194
|
-
public check(
|
|
195
|
-
request: TRequest,
|
|
196
|
-
role
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
motivation?: string,
|
|
212
|
-
dataForDebug?: { [key: string]: any }
|
|
231
|
+
public check(
|
|
232
|
+
request: TRequest,
|
|
233
|
+
role?: TUserRole | false,
|
|
234
|
+
): TUser | null;
|
|
235
|
+
|
|
236
|
+
public check(
|
|
237
|
+
request: TRequest,
|
|
238
|
+
role: TUserRole | false,
|
|
239
|
+
feature: FeatureKeys,
|
|
240
|
+
action?: string,
|
|
241
|
+
): TUser | null;
|
|
242
|
+
|
|
243
|
+
public check(
|
|
244
|
+
request: TRequest,
|
|
245
|
+
role: TUserRole | false = 'USER',
|
|
246
|
+
feature?: FeatureKeys,
|
|
247
|
+
action?: string,
|
|
213
248
|
): TUser | null {
|
|
214
249
|
|
|
215
250
|
const user = request.user;
|
|
216
251
|
|
|
217
|
-
this.config.debug && console.warn(LogPrefix, `Check auth, role = ${role}. Current user =`, user?.name,
|
|
252
|
+
this.config.debug && console.warn(LogPrefix, `Check auth, role = ${role}. Current user =`, user?.name, feature);
|
|
218
253
|
|
|
219
254
|
if (user === undefined) {
|
|
220
255
|
|
|
@@ -223,13 +258,13 @@ export default abstract class AuthService<
|
|
|
223
258
|
// Shoudln't be logged
|
|
224
259
|
} else if (role === false) {
|
|
225
260
|
|
|
226
|
-
return user;
|
|
261
|
+
return user as TUser;
|
|
227
262
|
|
|
228
263
|
// Not connected
|
|
229
264
|
} else if (user === null) {
|
|
230
265
|
|
|
231
266
|
console.warn(LogPrefix, "Refusé pour anonyme (" + request.ip + ")");
|
|
232
|
-
throw new AuthRequired('Please login to continue',
|
|
267
|
+
throw new AuthRequired('Please login to continue', feature as any, action as any);
|
|
233
268
|
|
|
234
269
|
// Insufficient permissions
|
|
235
270
|
} else if (!user.roles.includes(role)) {
|
|
@@ -244,7 +279,7 @@ export default abstract class AuthService<
|
|
|
244
279
|
|
|
245
280
|
}
|
|
246
281
|
|
|
247
|
-
return user;
|
|
282
|
+
return user as TUser;
|
|
248
283
|
}
|
|
249
284
|
|
|
250
|
-
}
|
|
285
|
+
}
|