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.
Files changed (66) hide show
  1. package/cli/app/config.ts +54 -0
  2. package/cli/app/index.ts +195 -0
  3. package/cli/bin.js +35 -0
  4. package/cli/commands/build.ts +34 -0
  5. package/cli/commands/deploy/app.ts +29 -0
  6. package/cli/commands/deploy/web.ts +60 -0
  7. package/cli/commands/dev.ts +109 -0
  8. package/cli/commands/init.ts +85 -0
  9. package/cli/compiler/client/identite.ts +72 -0
  10. package/cli/compiler/client/index.ts +335 -0
  11. package/cli/compiler/common/babel/index.ts +170 -0
  12. package/cli/compiler/common/babel/plugins/index.ts +0 -0
  13. package/cli/compiler/common/babel/plugins/services.ts +586 -0
  14. package/cli/compiler/common/babel/routes/imports.ts +127 -0
  15. package/cli/compiler/common/babel/routes/routes.ts +1130 -0
  16. package/cli/compiler/common/files/autres.ts +39 -0
  17. package/cli/compiler/common/files/images.ts +42 -0
  18. package/cli/compiler/common/files/style.ts +80 -0
  19. package/cli/compiler/common/index.ts +160 -0
  20. package/cli/compiler/index.ts +564 -0
  21. package/cli/compiler/server/index.ts +211 -0
  22. package/cli/index.ts +189 -0
  23. package/cli/paths.ts +165 -0
  24. package/cli/print.ts +12 -0
  25. package/cli/tsconfig.json +42 -0
  26. package/cli/utils/index.ts +22 -0
  27. package/cli/utils/keyboard.ts +78 -0
  28. package/client/app/index.ts +2 -0
  29. package/client/components/Dialog/Manager.tsx +3 -49
  30. package/client/components/Dialog/index.less +3 -1
  31. package/client/components/index.ts +1 -2
  32. package/client/services/router/index.tsx +6 -16
  33. package/common/errors/index.tsx +12 -31
  34. package/doc/TODO.md +1 -1
  35. package/package.json +58 -20
  36. package/server/app/container/console/index.ts +1 -1
  37. package/server/services/auth/index.ts +62 -27
  38. package/server/services/auth/router/request.ts +17 -6
  39. package/server/services/router/http/index.ts +1 -1
  40. package/server/services/router/response/index.ts +1 -1
  41. package/server/services/schema/request.ts +28 -10
  42. package/tsconfig.common.json +2 -1
  43. package/changelog.md +0 -5
  44. package/client/components/Button.tsx +0 -298
  45. package/client/components/Dialog/card.tsx +0 -208
  46. package/client/data/input.ts +0 -32
  47. package/client/pages/bug.tsx.old +0 -60
  48. package/templates/composant.tsx +0 -40
  49. package/templates/form.ts +0 -30
  50. package/templates/modal.tsx +0 -47
  51. package/templates/modele.ts +0 -56
  52. package/templates/page.tsx +0 -74
  53. package/templates/route.ts +0 -43
  54. package/templates/service.ts +0 -75
  55. package/vscode/copyimportationpath/.eslintrc.json +0 -24
  56. package/vscode/copyimportationpath/.vscodeignore +0 -12
  57. package/vscode/copyimportationpath/CHANGELOG.md +0 -9
  58. package/vscode/copyimportationpath/README.md +0 -3
  59. package/vscode/copyimportationpath/copyimportationpath-0.0.1.vsix +0 -0
  60. package/vscode/copyimportationpath/out/extension.js +0 -206
  61. package/vscode/copyimportationpath/out/extension.js.map +0 -1
  62. package/vscode/copyimportationpath/package-lock.json +0 -4536
  63. package/vscode/copyimportationpath/package.json +0 -86
  64. package/vscode/copyimportationpath/src/extension.ts +0 -300
  65. package/vscode/copyimportationpath/tsconfig.json +0 -22
  66. 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
@@ -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
- } else {
163
-
164
- render = (
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,6 +1,8 @@
1
- @import (reference) "@/client/assets/vars.less";
2
1
 
2
+ @c1: #6c5dd3; // Should be darker than c1
3
+ @spacing: 1.2em;
3
4
  @toast-zindex: 200;
5
+ @radius: 1rem;
4
6
 
5
7
  #modals,
6
8
  #toasts {
@@ -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 | ServerRouter;
59
+ export type Router = ClientRouter | TAnyRouter;
60
60
 
61
- export type Request = ClientRequest<ClientRouter> | ServerRequest<ServerRouter>;
61
+ export type Request = ClientRequest<ClientRouter> | ServerRequest<TAnyRouter>;
62
62
 
63
- export type Response = ClientResponse<ClientRouter> | ServerResponse<ServerRouter>;
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.context.modal.show(() => (
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
  }
@@ -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?: string,
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?: string } {
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: string,
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, (details as any).feature, details );
292
+ case 401: return new AuthRequired( message, details["feature"], details["action"], details );
312
293
 
313
- case 402: return new UpgradeRequired( message, details.feature, 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
@@ -34,7 +34,7 @@ abstract class Controller<
34
34
 
35
35
  ```typescript
36
36
  //? /headhunter/missions/suggested'
37
- class Missions extends Controller<CrossPath["router"]> {
37
+ class Missions extends Controller<UniqueDomains["router"]> {
38
38
 
39
39
  auth = 'USER';
40
40
 
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.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
- "@lexical/file": "^0.19.0",
17
- "@lexical/headless": "^0.18.0",
18
- "@lexical/html": "^0.18.0",
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
- "array-move": "^3.0.1",
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
- "chart.js": "^3.6.2",
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
- "file-type": "^16.5.3",
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
- "js-cookie": "^3.0.1",
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
- "picomatch": "^2.3.1",
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
- "react-scrollbars-custom": "^4.0.27",
71
- "react-slider": "^2.0.1",
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/5htp-core/';
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
- export type TUserRole = typeof UserRoles[number]
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, request: TRequest ): string {
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
- request.res.cookie('authorization', token, {
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: TUserRole,
197
- motivation?: string,
198
- dataForDebug?: { [key: string]: any }
199
- ): TUser;
200
-
201
- public check(
202
- request: TRequest,
203
- role: false,
204
- motivation?: string,
205
- dataForDebug?: { [key: string]: any }
206
- ): null;
207
-
208
- public check(
209
- request: TRequest,
210
- role: TUserRole | false = 'USER',
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, motivation);
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', motivation, dataForDebug);
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
+ }