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
@@ -8,7 +8,6 @@ import jwt from 'jsonwebtoken';
8
8
  // Core
9
9
  import type { default as Router, Request as ServerRequest, TAnyRouter } from '@server/services/router';
10
10
  import RequestService from '@server/services/router/request/service';
11
- import { InputError, AuthRequired, Forbidden } from '@common/errors';
12
11
 
13
12
  // Specific
14
13
  import type AuthenticationRouterService from '.';
@@ -45,10 +44,22 @@ export default class UsersRequestService<
45
44
  return this.users.logout( this.request );
46
45
  }
47
46
 
47
+ public check(): TUser;
48
+
48
49
  // TODO: return user type according to entity
49
- public check(role: TUserRole, motivation?: string, dataForDebug?: {}): TUser;
50
- public check(role: false, motivation?: string, dataForDebug?: {}): null;
51
- public check(role: TUserRole | boolean = 'USER', motivation?: string, dataForDebug?: {}): TUser | null {
52
- return this.users.check( this.request, role, motivation, dataForDebug );
50
+ public check(role: TUserRole, feature: null): TUser;
51
+
52
+ public check(role: false): null;
53
+
54
+ public check(role: TUserRole, feature: FeatureKeys, action?: string): TUser;
55
+
56
+ public check(role: false, feature: FeatureKeys, action?: string): null;
57
+
58
+ public check(
59
+ role: TUserRole | false = 'USER',
60
+ feature?: FeatureKeys | null,
61
+ action?: string
62
+ ) {
63
+ return this.users.check( this.request, role, feature, action ) as any;
53
64
  }
54
- }
65
+ }
@@ -193,7 +193,7 @@ export default class HttpServer {
193
193
 
194
194
  routes.use( csp.expressCspHeader({
195
195
  directives: {
196
- 'script-src': [csp.INLINE, csp.SELF,
196
+ 'script-src': [csp.INLINE, csp.SELF, csp.UNSAFE_EVAL,
197
197
  ...this.config.csp.scripts
198
198
  ]
199
199
  }
@@ -52,7 +52,7 @@ export type TRouterContext<TRouter extends TServerRouter> = (
52
52
  Router: TRouter,
53
53
  }
54
54
  & TRouterContextServices<TRouter>
55
- //& TRouterRequestContext<TRouter>
55
+ & TRouterRequestContext<TRouter>
56
56
  )
57
57
 
58
58
  export type TRouterContextServices<
@@ -4,7 +4,6 @@
4
4
 
5
5
  // Npm
6
6
  import zod from 'zod';
7
- import { SomeType } from 'zod/v4/core';
8
7
 
9
8
  // Core
10
9
  import {
@@ -24,6 +23,18 @@ export type TConfig = {
24
23
  debug?: boolean
25
24
  }
26
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
+ }
37
+
27
38
  /*----------------------------------
28
39
  - SERVICE
29
40
  ----------------------------------*/
@@ -32,18 +43,25 @@ export default(
32
43
  config: TConfig,
33
44
  router = request.router,
34
45
  app = router.app
35
- ) => ({
36
-
37
- ...schema,
46
+ ) => {
38
47
 
39
- validate( fields: zod.ZodSchema | { [key: string]: zod.ZodSchema } ) {
48
+ function validate<TSchema extends TValidationSchema>( fields: TSchema ): zod.output<TSchema>;
49
+ function validate<TShape extends TValidationShape>( fields: TShape ): zod.output<zod.ZodObject<TShape>>;
50
+ function validate( fields: TValidationSchema | TValidationShape ) {
40
51
 
41
52
  config.debug && console.log(LogPrefix, "Validate request data:", request.data);
42
53
 
43
- const schema = typeof fields === 'object' ? zod.object(fields) : fields;
54
+ const validationSchema = isZodSchema(fields) ? fields : zod.object(fields);
44
55
 
45
- const preprocessedSchema = preprocessSchema(schema);
56
+ //const preprocessedSchema = preprocessSchema(validationSchema);
46
57
 
47
- return preprocessedSchema.parse(request.data);
48
- },
49
- })
58
+ return validationSchema.parse(request.data);
59
+ }
60
+
61
+ return {
62
+
63
+ ...schema,
64
+
65
+ validate,
66
+ }
67
+ }
@@ -40,5 +40,6 @@
40
40
  "react/jsx-runtime": ["preact/jsx-runtime"]
41
41
  },
42
42
  },
43
- "include": ["."]
43
+ "include": ["."],
44
+ "exclude": ["cli"]
44
45
  }
package/changelog.md DELETED
@@ -1,5 +0,0 @@
1
- # 01/01/2023:
2
-
3
- * Redesigned systems service. Pass app instance servces list through constructor attribute instead of importing instance
4
- * Update babel-plugn-glob-import
5
- *
@@ -1,298 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import React from 'react';
7
- import { VNode, RefObject,ComponentChild } from 'preact';
8
-
9
- // Core
10
- import { shouldOpenNewTab } from '@client/services/router/components/Link';
11
- import { history } from '@client/services/router/request/history';
12
- import useContext from '@/client/context';
13
-
14
- /*----------------------------------
15
- - TYPES
16
- ----------------------------------*/
17
-
18
- export type Props = {
19
-
20
- id?: string,
21
- refElem?: RefObject<HTMLElement>,
22
-
23
- icon?: ComponentChild,
24
- iconR?: ComponentChild,
25
-
26
- prefix?: ComponentChild,
27
- suffix?: ComponentChild,
28
-
29
- tag?: "a" | "button",
30
- type?: 'guide' | 'primary' | 'secondary' | 'link',
31
- shape?: 'default' | 'icon' | 'tile' | 'pill' | 'custom',
32
- size?: TComponentSize,
33
- class?: string,
34
-
35
- state?: [string, React.StateUpdater<string>],
36
- active?: boolean,
37
- selected?: boolean,
38
- disabled?: boolean,
39
- loading?: boolean,
40
- autoFocus?: boolean,
41
- onClick?: (e: MouseEvent) => any,
42
- async?: boolean,
43
-
44
- submenu?: ComponentChild,
45
- nav?: boolean | 'exact'
46
-
47
- // SEO: if icon only, should provinde a hint (aria-label)
48
- } & ({
49
- hint: string,
50
- children?: ComponentChild | ComponentChild[],
51
- } | {
52
- children: ComponentChild | ComponentChild[],
53
- hint?: string,
54
- }) & (TButtonProps | TLinkProps)
55
-
56
- export type TButtonProps = React.JSX.HTMLAttributes<HTMLButtonElement>
57
-
58
- export type TLinkProps = React.JSX.HTMLAttributes<HTMLAnchorElement>
59
-
60
- /*----------------------------------
61
- - HELPERS
62
- ----------------------------------*/
63
- const trimSlash = (str: string): string => {
64
- return str.endsWith('/') ? str.slice(0, -1) : str;
65
- }
66
-
67
- const isCurrentUrl = (currentUrl: string, url: string, exact?: boolean) => {
68
- return (
69
- (exact && (url === currentUrl || trimSlash(url) === currentUrl))
70
- ||
71
- (!exact && currentUrl.startsWith(url))
72
- )
73
- }
74
-
75
- /*----------------------------------
76
- - CONTROLEUR
77
- ----------------------------------*/
78
- export default ({
79
-
80
- id,
81
-
82
- // Content
83
- icon, prefix,
84
- children,
85
- iconR, suffix,
86
- submenu,
87
- nav,
88
- hint,
89
-
90
- // Style
91
- class: className,
92
- shape,
93
- size,
94
- type,
95
-
96
- // Interactions
97
- active,
98
- selected,
99
- state: stateUpdater,
100
- disabled,
101
- loading,
102
- //autoFocus,
103
- async,
104
-
105
- // HTML attributes
106
- tag: Tag,
107
- refElem,
108
- ...props
109
-
110
- }: Props) => {
111
-
112
- const ctx = useContext();
113
- let [isSelected, setIsSelected] = React.useState(false);
114
- let [isActive, setIsActive] = React.useState(false);
115
- const [isLoading, setLoading] = React.useState(false);
116
-
117
- if (isLoading || loading) {
118
- icon = <i src="spin" />
119
- iconR = undefined;
120
- disabled = true;
121
- }
122
-
123
- if (stateUpdater && id !== undefined) {
124
- const [active, setActive] = stateUpdater;
125
- if (id === active)
126
- isSelected = true;
127
- props.onClick = () => setActive(id);
128
- }
129
-
130
- // Hint
131
- if (hint !== undefined) {
132
- props['aria-label'] = hint;
133
- props.title = hint;
134
- }
135
-
136
- // Shape classes
137
- const classNames: string[] = ['btn'];
138
- if (className)
139
- classNames.push(className);
140
-
141
- if (shape !== undefined) {
142
- if (shape === 'tile')
143
- classNames.push('col');
144
- else
145
- classNames.push(shape);
146
- }
147
-
148
- if (size !== undefined)
149
- classNames.push(size);
150
-
151
- if (icon) {
152
- if (children === undefined)
153
- classNames.push('icon');
154
- }
155
-
156
- // state classes
157
- const [isMouseDown, setMouseDown] = React.useState(false);
158
- props.onMouseDown = () => setMouseDown(true);
159
- props.onMouseUp = () => setMouseDown(false);
160
- props.onMouseLeave = () => setMouseDown(false);
161
-
162
- // Theming & state
163
- if (isMouseDown)
164
- classNames.push('pressed');
165
- else if (selected || isSelected === true)
166
- classNames.push('bg accent');
167
- else if (type !== undefined)
168
- classNames.push(type === 'link' ? type : (' bg ' + type));
169
-
170
- if (active || isActive === true)
171
- classNames.push('active');
172
-
173
- // Icon
174
- if (prefix === undefined && icon !== undefined)
175
- prefix = typeof icon === "string" ? <i class={"svg-" + icon} /> : icon;
176
- if (suffix === undefined && iconR !== undefined)
177
- suffix = typeof iconR === "string" ? <i class={"svg-" + iconR} /> : iconR;
178
-
179
- // Render
180
- if ('link' in props || Tag === "a") {
181
-
182
- // Link (only if enabled)
183
- if (!disabled) {
184
-
185
- props.href = props.link;
186
-
187
- // External = open in new tab by default
188
- if (shouldOpenNewTab( props.href, props.target ))
189
- props.target = '_blank';
190
- }
191
-
192
- // Nav
193
- if (nav && props.target === undefined) {
194
-
195
- const checkIfCurrentUrl = (url: string) =>
196
- isCurrentUrl(url, props.link, nav === 'exact');
197
-
198
- React.useEffect(() => {
199
-
200
- // Init
201
- if (checkIfCurrentUrl(ctx.request.path))
202
- setIsActive(true);
203
-
204
- // On location change
205
- return history?.listen(({ location }) => {
206
-
207
- setIsActive( checkIfCurrentUrl(location.pathname) );
208
-
209
- })
210
-
211
- }, []);
212
- }
213
-
214
- Tag = 'a';
215
-
216
- } else {
217
- Tag = 'button';
218
-
219
- // Avoid to trigget onclick when presing enter
220
- if (type !== 'primary')
221
- props.type = 'button';
222
- else
223
- props.type = 'submit';
224
- }
225
-
226
- let render: VNode = (
227
- <Tag {...props} id={id} class={classNames.join(' ')} disabled={disabled} ref={refElem} onClick={(e: MouseEvent) => {
228
-
229
- // annulation si:
230
- // - Pas clic gauche
231
- // - Event annulé
232
- if (e.button !== 0)
233
- return;
234
-
235
- // Disabled
236
- if (disabled)
237
- return false;
238
-
239
- // Custom event
240
- if (props.onClick !== undefined) {
241
-
242
- const returned = props.onClick(e);
243
- if (async && returned?.then) {
244
- setLoading(true);
245
- returned.finally(() => setLoading(false));
246
- }
247
- }
248
-
249
- // Link
250
- let nativeEvent: boolean = false;
251
- if (('link' in props) && !e.defaultPrevented) {
252
-
253
- // Nouvelle fenetre = event par defaut
254
- if (props.target === '_blank') {
255
-
256
- nativeEvent = true;
257
-
258
- // Page change = loading indicator
259
- } else if (props.target === "_self") {
260
-
261
- setLoading(true);
262
- window.location.href = props.link;
263
-
264
- } else {
265
-
266
- history?.push(props.link);
267
- }
268
- }
269
-
270
- if (!nativeEvent) {
271
- e.preventDefault();
272
- return false;
273
- }
274
- }}>
275
- {prefix}
276
- {children === undefined
277
- ? null
278
- : shape === 'custom'
279
- ? children : (
280
- <span class={"label"}>
281
- {children}
282
- </span>
283
- )}
284
- {suffix}
285
- </Tag>
286
- )
287
-
288
- if (Tag === "li" || submenu) {
289
- render = (
290
- <li>
291
- {render}
292
- {submenu}
293
- </li>
294
- )
295
- }
296
-
297
- return render;
298
- }
@@ -1,208 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import React from 'react';
7
-
8
- // Composants globaux
9
- import Button from '@client/components/Button';
10
-
11
- /*----------------------------------
12
- - TYPES
13
- ----------------------------------*/
14
- import { ComponentChild } from 'preact';
15
-
16
- type funcBtns = () => void
17
-
18
- type Boutons = { [label: string]: funcBtns }
19
-
20
- /*----------------------------------
21
- - CONTENU
22
- ----------------------------------*/
23
- export type Props = {
24
-
25
- // Informations modale
26
- type?: 'primary' | 'success' | 'warning' | 'error' | 'loading' | 'info',
27
- cover?: string,
28
- icon?: ComponentChild,
29
- title?: string | ComponentChild,
30
- className?: string,
31
-
32
- children?: ComponentChild,
33
- isToast?: boolean,
34
- width?: number,
35
-
36
- footer?: ComponentChild,
37
- boutons?: Boutons | null, // nul = pas de footer
38
- defaultBtn?: string,
39
-
40
- prison?: boolean,
41
- /* Hide after x seconds */autohide?: number | false,
42
- close?: funcBtns,
43
- onClose?: () => Promise<any>,
44
- }
45
-
46
- export default ({
47
-
48
- // Content
49
- type,
50
- cover,
51
- icon,
52
- title,
53
- className = '',
54
-
55
- children,
56
- isToast,
57
- width,
58
-
59
- footer,
60
- boutons,
61
- defaultBtn,
62
-
63
- onClose,
64
- close,
65
- autohide,
66
- prison,
67
-
68
- }: Props) => {
69
-
70
- // Boutons
71
- if (footer === undefined && boutons !== null) {
72
-
73
- // Default buttons
74
- if (boutons === undefined || !Object.keys(boutons).length) {
75
-
76
- // Toast: by default, if no buttons, we autohide after 3 seconds
77
- if (autohide === undefined)
78
- autohide = 3;
79
-
80
- // If isToast, we show a default OK button
81
- if (close && !isToast)
82
- boutons = { 'Ok': () => close(true) };
83
- else
84
- boutons = null;
85
-
86
- }
87
-
88
- if (boutons !== null) {
89
-
90
- const nbBtns = Object.keys(boutons).length;
91
-
92
- footer = Object.entries(boutons).map(([texte, action]: [string, Function], index: number) => {
93
- const dernier = nbBtns > 1 && index === nbBtns - 1;
94
- return (
95
- <Button
96
- async
97
- onClick={() => action()}
98
- type={(defaultBtn === undefined ? dernier : (defaultBtn === texte)) ? 'primary' : undefined}
99
- >
100
- {texte}
101
- </Button>
102
- )
103
- });
104
- }
105
- }
106
-
107
- if (typeof icon === 'string')
108
- icon = <i class={"svg-" + icon} />
109
- else if (icon === undefined)
110
- switch (type) {
111
- case 'info':
112
- icon = <i src="info-circle" />
113
- break;
114
- case 'success':
115
- icon = <i src="check-circle" />
116
- break;
117
- case 'warning':
118
- icon = <i src="exclamation-circle" />
119
- break;
120
- case 'error':
121
- icon = <i src="times-circle" />
122
- break;
123
- case 'loading':
124
- icon = <i src="spin" />
125
- break;
126
- }
127
-
128
- // Autohide
129
- if (isToast)
130
- React.useEffect(() => {
131
- if (autohide) {
132
- const timeout = setTimeout(() => close(true), autohide * 1000);
133
- return () => clearTimeout(timeout);
134
- }
135
- }, []);
136
-
137
- let render = isToast ? (
138
- <div class="card row bg dark" onClick={() => isToast && !prison && close(true)}>
139
-
140
- {icon}
141
-
142
- <div>
143
-
144
- {typeof title === "string" ? (
145
- <strong>{title}</strong>
146
- ) : title}
147
-
148
- {children}
149
-
150
- </div>
151
-
152
- </div>
153
- ) : (
154
- <div class={"card pd-2 col al-top " + className} style={width === undefined
155
- ? {}
156
- : { minWidth: width + "px", maxWidth: width + "px" }
157
- }>
158
-
159
- {(title || icon) && (
160
- <header {...{
161
- class: ('col ' + type),
162
- style: cover ? {
163
- backgroundImage: 'url(' + cover + ')'
164
- } : undefined
165
- }}>
166
-
167
- {icon}
168
-
169
- {typeof title === "string" ? (
170
- <strong>{title}</strong>
171
- ) : title}
172
-
173
- {(!prison && close) && (
174
- <Button class="close" icon="times" size="s" shape="pill" onClick={async () => {
175
- if (typeof close === "function") {
176
-
177
- if (onClose !== undefined)
178
- onClose(false);
179
- else
180
- close(false);
181
- }
182
- }} />
183
- )}
184
-
185
- </header>
186
- )}
187
-
188
- {children && (
189
- <div class="col content">
190
-
191
- {children}
192
-
193
- </div>
194
- )}
195
-
196
- {footer && (
197
- <footer class="row fill actions">
198
-
199
- {footer}
200
-
201
- </footer>
202
- )}
203
-
204
- </div>
205
- )
206
-
207
- return render;
208
- }
@@ -1,32 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Libs métier
6
- import buildValidators, { champ } from '@common/data/input/validators/build';
7
- import { validateurFichier, TOptsValidateurFichier } from '@common/data/input/validators/basic';
8
-
9
- /*----------------------------------
10
- - VALIDATEURS
11
- ----------------------------------*/
12
-
13
- export default buildValidators({
14
-
15
- file: ({ ...opts }: TOptsValidateurFichier & {}) => champ<object>('fichier', {
16
- ...opts,
17
- valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
18
-
19
- console.log('VALIDER FICHIER COTÉ CLIENT', val);
20
-
21
- // Chaine = url ancien fichier = conservation = sera ignoré coté serveur
22
- if (typeof val === 'string')
23
- return val;
24
-
25
- // Validation universelle
26
- val = await validateurFichier(opts, val, donneesSaisie, donneesRetour);
27
-
28
- return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
29
- }
30
- })
31
-
32
- });