5htp-core 0.2.1 → 0.2.2-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/package.json +10 -3
  2. package/src/client/app/index.ts +2 -2
  3. package/src/client/assets/css/components/card.less +0 -3
  4. package/src/client/assets/css/components/other.less +2 -4
  5. package/src/client/assets/css/components/table.less +1 -2
  6. package/src/client/assets/css/components.less +4 -0
  7. package/src/client/assets/css/core.less +0 -1
  8. package/src/client/assets/css/theme.less +2 -2
  9. package/src/client/assets/css/utils/medias.less +21 -0
  10. package/src/client/components/Card/index.tsx +8 -5
  11. package/src/client/components/Dialog/index.less +3 -3
  12. package/src/client/components/Row/index.less +2 -0
  13. package/src/client/components/Row/index.tsx +44 -10
  14. package/src/client/components/Video/index.less +39 -0
  15. package/src/client/components/Video/index.tsx +69 -0
  16. package/src/client/components/containers/Popover/index.tsx +2 -2
  17. package/src/client/components/data/Time.tsx +1 -1
  18. package/src/client/components/data/progressbar/circular/index.tsx +1 -1
  19. package/src/client/components/index.ts +24 -8
  20. package/src/client/components/input/BaseV2/index.tsx +0 -1
  21. package/src/client/components/{input/BaseV2/index.less → inputv3/base.less} +1 -1
  22. package/src/client/components/inputv3/base.tsx +73 -0
  23. package/src/client/components/{input/UploadImage → inputv3/file}/Bouton.tsx +0 -0
  24. package/src/client/components/inputv3/file/FileToUpload.ts +34 -0
  25. package/src/client/components/inputv3/file/index.less +59 -0
  26. package/src/client/components/inputv3/file/index.tsx +157 -0
  27. package/src/client/components/{input → inputv3/string}/index.tsx +41 -27
  28. package/src/client/pages/bug.tsx +3 -4
  29. package/src/client/services/router/index.tsx +0 -1
  30. package/src/client/services/router/request/api.ts +20 -12
  31. package/src/client/services/router/request/multipart.ts +27 -0
  32. package/src/common/data/chaines/greetings.ts +1 -1
  33. package/src/common/data/dates.ts +1 -1
  34. package/src/common/data/input/validate.ts +0 -9
  35. package/src/common/data/markdown.ts +1 -1
  36. package/src/common/errors/index.ts +16 -12
  37. package/src/common/router/request/api.ts +11 -3
  38. package/src/common/validation/schema.ts +21 -20
  39. package/src/common/validation/validators.ts +3 -6
  40. package/src/server/app/commands.ts +149 -0
  41. package/src/server/app/index.ts +25 -5
  42. package/src/server/app/service.ts +4 -0
  43. package/src/server/services/cache/commands.ts +41 -0
  44. package/src/server/services/cache/index.ts +102 -34
  45. package/src/server/services/console/index.ts +1 -1
  46. package/src/server/services/database/connection.ts +38 -22
  47. package/src/server/services/database/datatypes.ts +51 -12
  48. package/src/server/services/database/index.ts +133 -40
  49. package/src/server/services/database/metas.ts +63 -37
  50. package/src/server/services/database/repository.ts +26 -0
  51. package/src/server/services/email/index.ts +102 -42
  52. package/src/server/services/fetch/index.ts +110 -0
  53. package/src/server/services/router/http/multipart.ts +70 -41
  54. package/src/server/services/router/index.ts +35 -4
  55. package/src/server/services/router/request/index.ts +8 -6
  56. package/src/server/services/schema/index.ts +4 -11
  57. package/src/server/services/schema/request.ts +16 -7
  58. package/src/server/services/schema/router.ts +6 -2
  59. package/src/server/{services_old → services/security/encrypt}/aes.ts +33 -14
  60. package/src/server/services/users/index.ts +3 -3
  61. package/src/server/services/users/router/index.ts +0 -2
  62. package/src/types/global/utils.d.ts +11 -1
  63. package/tsconfig.common.json +3 -0
  64. package/src/client/components/input/Textarea.tsx +0 -57
  65. package/src/client/components/input/Upload.tsx +0 -5
  66. package/src/client/components/input/UploadImage/index.less +0 -93
  67. package/src/client/components/input/UploadImage/index.tsx +0 -220
  68. package/src/common/data/file.ts +0 -25
@@ -0,0 +1,59 @@
1
+ .input.upload {
2
+
3
+ position: relative;
4
+ overflow: hidden;
5
+
6
+ border-radius: @radius;
7
+ border: dashed 3px var(--cLine);
8
+ background: @cBgPage + #090909;
9
+
10
+ padding: @spacing;
11
+ width: 100%;
12
+ min-height: 200px;
13
+ height: 14.15rem;
14
+
15
+ .preview,
16
+ .indication,
17
+ input[type="file"] {
18
+ position: absolute;
19
+ top: 0; left: 0;
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+
24
+ input[type="file"] {
25
+ cursor: pointer;
26
+ opacity: 0;
27
+ z-index: 2;
28
+ }
29
+
30
+ .indication {
31
+ transition: all .1s linear;
32
+ background: inherit;
33
+ opacity: 0;
34
+ z-index: 1;
35
+ }
36
+
37
+ .actions {
38
+ position: absolute;
39
+ right: @spacing;
40
+ bottom: @spacing;
41
+ z-index: 3;
42
+ }
43
+
44
+ // When no file selected, or when hover
45
+ .indication:first-child,
46
+ &:hover .indication {
47
+ opacity: 0.9;
48
+ }
49
+
50
+ // Image preview
51
+ > img {
52
+ border-radius: @radius;
53
+ max-width: 100%;
54
+ height: 100%;
55
+
56
+ display: block;
57
+ margin: 0 auto;
58
+ }
59
+ }
@@ -0,0 +1,157 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+ // Npm
5
+ import React from 'react';
6
+ import { ComponentChild } from 'preact';
7
+
8
+ // Composants généraux
9
+ import Bouton from '@client/components/button';
10
+
11
+ // Libs
12
+ import useContext from '@/client/context';
13
+
14
+ // specific
15
+ import FileToUpload from './FileToUpload';
16
+
17
+ // Ressources
18
+ import './index.less';
19
+
20
+ /*----------------------------------
21
+ - OUTILS
22
+ ----------------------------------*/
23
+ export { default as FileToUpload } from './FileToUpload';
24
+
25
+ export const createImagePreview = (file: Blob) => new Promise((resolve, reject) => {
26
+
27
+ // Conversion de l'image en base24 pour l'afficher
28
+ const reader = new FileReader();
29
+ let imageBase64: string | null = null;
30
+ reader.addEventListener('load', () => {
31
+
32
+ var enc = new TextDecoder("utf-8");
33
+
34
+ // reader.result pout être une chaine ou un arraybuffer
35
+ imageBase64 = reader.result instanceof ArrayBuffer
36
+ ? enc.decode(reader.result) // ArrayBuffer => Chaine
37
+ : reader.result;
38
+
39
+ // Affichage
40
+ resolve(imageBase64);
41
+ });
42
+
43
+ reader.readAsDataURL(file);
44
+ });
45
+
46
+ // Instanciate FileToUpload from browser side File
47
+ const normalizeFile = (file: File) => new FileToUpload({
48
+ name: file.name,
49
+ type: file.type,
50
+ size: file.size,
51
+ data: file,
52
+ //original: file
53
+ })
54
+
55
+ /*----------------------------------
56
+ - TYPES
57
+ ----------------------------------*/
58
+
59
+ export type Props = {
60
+
61
+ // Input
62
+ title: ComponentChild,
63
+ value?: FileToUpload,
64
+
65
+ // Display
66
+ emptyText?: ComponentChild,
67
+ className?: string,
68
+ previewUrl?: string,
69
+
70
+ // Actions
71
+ onChange: (file: FileToUpload | undefined) => void
72
+ remove?: () => Promise<void>,
73
+ }
74
+
75
+ /*----------------------------------
76
+ - COMPOSANT
77
+ ----------------------------------*/
78
+ export default ({
79
+
80
+ // Input
81
+ title,
82
+ value: file,
83
+ className,
84
+
85
+ // Display
86
+ emptyText = 'Click here to select a File',
87
+ previewUrl: previewUrlInit,
88
+
89
+ // Actions
90
+ onChange
91
+ }: Props) => {
92
+
93
+ /*----------------------------------
94
+ - INITIALIZE
95
+ ----------------------------------*/
96
+
97
+ const [previewUrl, setPreviewUrl] = React.useState<string | undefined>(previewUrlInit);
98
+
99
+ className = 'input upload ' + (className === undefined ? '' : ' ' + className)
100
+
101
+ /*----------------------------------
102
+ - ACTIONS
103
+ ----------------------------------*/
104
+
105
+ const selectFile = (fileSelectEvent: any) => {
106
+ const selectedfile = fileSelectEvent.target.files[0] as File;
107
+ if (selectedfile) {
108
+
109
+ const fileToUpload = normalizeFile(selectedfile);
110
+
111
+ onChange(fileToUpload);
112
+ }
113
+ }
114
+
115
+ React.useEffect(() => {
116
+
117
+ // Image = decode & display preview
118
+ if (file !== undefined && file.type.startsWith('image/'))
119
+ createImagePreview(file.data).then(setPreviewUrl);
120
+ else
121
+ setPreviewUrl(undefined);
122
+
123
+ }, [file]);
124
+
125
+ /*----------------------------------
126
+ - RENDER
127
+ ----------------------------------*/
128
+ return <>
129
+ <label>{title}</label>
130
+
131
+ <div class={className}>
132
+
133
+ {file && <>
134
+ <div class="preview">
135
+
136
+ {previewUrl ? (
137
+ <img src={previewUrl} />
138
+ ) : file ? <>
139
+ <strong>{file.name}</strong>
140
+ </> : null}
141
+ </div>
142
+
143
+ <div class="row actions sp-05">
144
+
145
+ <Bouton class='fg error' icon="trash" shape="pill" size="s"
146
+ async onClick={() => onChange(undefined)} />
147
+ </div>
148
+ </>}
149
+
150
+ <div class="indication col al-center">
151
+ {emptyText}
152
+ </div>
153
+
154
+ <input type="file" onChange={selectFile} />
155
+ </div>
156
+ </>
157
+ }
@@ -8,41 +8,43 @@ import { ComponentChild, JSX } from 'preact';
8
8
  import TextareaAutosize from 'react-textarea-autosize';
9
9
 
10
10
  // Core libs
11
- import { useInput, InputBaseProps } from './BaseV2';
11
+ import { useInput, InputBaseProps } from '../base';
12
12
 
13
13
  /*----------------------------------
14
14
  - TYPES
15
15
  ----------------------------------*/
16
16
  export type Props = {
17
17
 
18
- type?: 'email' | 'password',
19
- multiline?: boolean, // true = textarea
20
- onPressEnter?: (value: string) => void,
21
-
22
18
  // Decoration
23
19
  icon?: string,
24
- prefix?: ComponentChild,
25
- suffix?: ComponentChild,
20
+ prefix?: React.VNode,
21
+ suffix?: React.VNode,
26
22
  iconR?: string,
27
23
 
24
+ // Behavior
25
+ type?: 'email' | 'password' | 'longtext',
26
+ choice?: string[] | ((input: string) => Promise<string[]>),
27
+ multiple?: boolean,
28
+
29
+ // Actions
30
+ onPressEnter?: (value: string) => void,
28
31
  inputRef?: React.Ref<HTMLInputElement>
29
-
30
32
  }
31
33
 
32
34
  /*----------------------------------
33
35
  - COMPOSANT
34
36
  ----------------------------------*/
35
37
  export default ({
38
+ // Behavoir
36
39
  type,
37
40
  icon, prefix, suffix, iconR,
38
- multiline,
39
41
  onPressEnter,
40
42
  inputRef,
41
43
  ...props
42
44
  }: Props & InputBaseProps<string> & Omit<JSX.HTMLAttributes<HTMLInputElement>, 'onChange'>) => {
43
45
 
44
46
  /*----------------------------------
45
- - STATE
47
+ - INIT
46
48
  ----------------------------------*/
47
49
 
48
50
  const [{ value, focus, fieldProps }, setValue, commitValue, setState] = useInput(props, '');
@@ -61,26 +63,37 @@ export default ({
61
63
  const refInput = inputRef || React.useRef<HTMLInputElement>();
62
64
 
63
65
  /*----------------------------------
64
- - RENDER
66
+ - ATTRIBUTES
65
67
  ----------------------------------*/
66
68
 
69
+ let className: string = 'input text';
70
+
67
71
  // Auto prefix
68
- if (prefix === undefined) {
69
- if (icon !== undefined)
70
- prefix = <i src={icon} />
71
- else if (type === 'password')
72
- prefix = <i src="key" />;
73
- else if (type === 'email')
74
- prefix = <i src="at" />;
75
- }
72
+ if (prefix === undefined && icon !== undefined)
73
+ prefix = <i src={icon} />
74
+
75
+ // Type
76
+ let Tag = 'input';
77
+ if (type === 'password') {
78
+
79
+ prefix = prefix || <i src="key" />;
80
+ fieldProps.type = 'password';
81
+
82
+ } else if (type === 'email') {
83
+
84
+ prefix = prefix || <i src="at" />;
85
+ fieldProps.type = 'email';
86
+
87
+ } else if (type === 'longtext') {
88
+
89
+ prefix = prefix || <i src="text" />;
90
+ Tag = TextareaAutosize;
76
91
 
77
- // Auto suffix
78
- if (suffix === undefined) {
79
- if (iconR !== undefined)
80
- suffix = <i src={iconR} />
81
92
  }
82
93
 
83
- let className: string = 'input text';
94
+ // Auto suffix
95
+ if (suffix === undefined && iconR !== undefined)
96
+ suffix = <i src={iconR} />
84
97
 
85
98
  // When no value, show the lable as a placeholder
86
99
  if (value === '')
@@ -91,8 +104,9 @@ export default ({
91
104
  if (props.className !== undefined)
92
105
  className += ' ' + props.className;
93
106
 
94
- const Tag = multiline ? TextareaAutosize : 'input';
95
-
107
+ /*----------------------------------
108
+ - RENDER
109
+ ----------------------------------*/
96
110
  return (
97
111
  <div class={className} onClick={() => refInput.current?.focus()}>
98
112
 
@@ -101,8 +115,8 @@ export default ({
101
115
  <div class="contValue">
102
116
 
103
117
  <Tag {...fieldProps}
118
+ // @ts-ignore: Property 'ref' does not exist on type 'IntrinsicAttributes'
104
119
  ref={refInput}
105
- type={type}
106
120
  value={value}
107
121
 
108
122
  onFocus={() => setState({ focus: true })}
@@ -5,8 +5,7 @@
5
5
  import React from 'react';
6
6
 
7
7
  // Core components
8
- import Button from '@client/components/button';
9
- import Textarea from '@client/components/input/Textarea';
8
+ import { Button, String } from '@client/components';
10
9
  import Card, { Props as CardProps } from '@client/components/Dialog/card';
11
10
 
12
11
  // Core libs
@@ -50,11 +49,11 @@ export default ({ ...self }: {} & CardProps) => {
50
49
 
51
50
  <p>What's the problem ?</p>
52
51
 
53
- <Textarea valeur={observation} onChange={setObservation} />
52
+ <String type="longtext" title="Description of the problem" value={observation} onChange={setObservation} />
54
53
 
55
54
  <p>What did you do just before the problem occurs ?</p>
56
55
 
57
- <Textarea valeur={before} onChange={setBefore} />
56
+ <String type="longtext" title="How the problem occured ?" value={before} onChange={setBefore} />
58
57
 
59
58
  </Card>
60
59
  )
@@ -14,7 +14,6 @@ import type {
14
14
  } from '@server/services/router';
15
15
  import type { TBasicSSrData } from '@server/services/router/response';
16
16
 
17
- import { Erreur } from '@common/errors';
18
17
  import BaseRouter, {
19
18
  defaultOptions, TRoute, TErrorRoute, TClientOrServerContext, TRouteModule
20
19
  } from '@common/router'
@@ -8,11 +8,14 @@ import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
8
8
  // Core
9
9
  import type { TApiResponseData } from '@server/services/router';
10
10
  import ApiClientService, {
11
+ TPostData,
11
12
  TApiFetchOptions, TFetcherList, TFetcherArgs, TFetcher
12
13
  } from '@common/router/request/api';
13
14
  import { instancierViaCode, NetworkError } from '@common/errors';
14
15
  import type ClientApplication from '@client/app';
15
16
 
17
+ import { toMultipart } from './multipart';
18
+
16
19
  // Specific
17
20
  import type { default as Router, Request } from '..';
18
21
 
@@ -34,7 +37,8 @@ export default class ApiClient implements ApiClientService {
34
37
  // APO Client needs to know the current request so we can monitor which api request is made from which page
35
38
  public constructor(
36
39
  public app: ClientApplication,
37
- public request: Request<Router>
40
+ public request: Request,
41
+ public router = request.router
38
42
  ) {
39
43
 
40
44
  }
@@ -42,16 +46,16 @@ export default class ApiClient implements ApiClientService {
42
46
  /*----------------------------------
43
47
  - HIGH LEVEL
44
48
  ----------------------------------*/
45
- public get = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
49
+ public get = <TData extends unknown = unknown>(path: string, data?: TPostData, opts?: TApiFetchOptions) =>
46
50
  this.createFetcher<TData>('GET', path, data, opts);
47
51
 
48
- public post = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
52
+ public post = <TData extends unknown = unknown>(path: string, data?: TPostData, opts?: TApiFetchOptions) =>
49
53
  this.createFetcher<TData>('POST', path, data, opts);
50
54
 
51
- public put = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
55
+ public put = <TData extends unknown = unknown>(path: string, data?: TPostData, opts?: TApiFetchOptions) =>
52
56
  this.createFetcher<TData>('PUT', path, data, opts);
53
57
 
54
- public delete = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
58
+ public delete = <TData extends unknown = unknown>(path: string, data?: TPostData, opts?: TApiFetchOptions) =>
55
59
  this.createFetcher<TData>('DELETE', path, data, opts);
56
60
 
57
61
 
@@ -108,9 +112,9 @@ export default class ApiClient implements ApiClientService {
108
112
  method, path, data, options,
109
113
  // For async calls: api.post(...).then((data) => ...)
110
114
  then: (callback: (data: any) => void) => this.fetchAsync<TData>(...args).then(callback),
111
- catch: (callback: (data: any) => void) => this.fetchAsync(...args).catch(callback),
112
- finally: (callback: () => void) => this.fetchAsync(...args).finally(callback),
113
- run: () => this.fetchAsync(...args)
115
+ catch: (callback: (data: any) => void) => this.fetchAsync<TData>(...args).catch(callback),
116
+ finally: (callback: () => void) => this.fetchAsync<TData>(...args).finally(callback),
117
+ run: () => this.fetchAsync<TData>(...args)
114
118
  };
115
119
  }
116
120
 
@@ -183,12 +187,16 @@ export default class ApiClient implements ApiClientService {
183
187
  };
184
188
 
185
189
  if (data) {
186
- if (method === "GET")
190
+ // URL params
191
+ if (method === "GET") {
187
192
  config.params = data;
188
- else {
193
+ // Post form data
194
+ } else if (options?.encoding === 'multipart') {
195
+ config.headers["Content-Type"] = 'multipart/form-data';
196
+ config.data = toMultipart(data);
197
+ // Post JSON
198
+ } else {
189
199
  config.data = data;
190
- if (data instanceof FormData)
191
- config.headers["Content-Type"] = 'multipart/form-data';
192
200
  }
193
201
  }
194
202
 
@@ -0,0 +1,27 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Core
6
+ import { TPostData } from '@common/router/request/api';
7
+ import { FileToUpload } from '@client/components/inputv3/file';
8
+
9
+ /*----------------------------------
10
+ - TYPES
11
+ ----------------------------------*/
12
+
13
+ /*----------------------------------
14
+ - UTILS
15
+ ----------------------------------*/
16
+ export const toMultipart = (postData: TPostData) => {
17
+
18
+ const formData = new FormData();
19
+ for (const key in postData) {
20
+ let data = postData[key];
21
+ if (typeof data === 'object' && (data instanceof FileToUpload))
22
+ data = data.data;
23
+ formData.append(key, data);
24
+ }
25
+
26
+ return formData;
27
+ }
@@ -24,4 +24,4 @@ const howareyou = () => {
24
24
  return howareyou_list[ index ];
25
25
  }
26
26
 
27
- export default (username: string) => hello() + ', ' + username + '. ' + howareyou();
27
+ export default (username: string, withHowAreYou: boolean = true) => hello() + ', ' + username + '. ' + (withHowAreYou ? howareyou() : '');
@@ -5,7 +5,7 @@ const timeAgo = new TimeAgo('en-US')
5
5
 
6
6
  import dayjs from 'dayjs';
7
7
 
8
- export const timeSince = (date: Date | number | string, prefixe: boolean = false) => {
8
+ export const timeSince = (date: Date | number | string) => {
9
9
 
10
10
  if (date === undefined)
11
11
  return 'Inconnu';
@@ -3,15 +3,6 @@
3
3
  /*----------------------------------
4
4
  - DEPENDANCES
5
5
  ----------------------------------*/
6
-
7
- // Npm
8
- import { ComponentChild } from 'preact'
9
-
10
- // Libs
11
- import { Erreur, TListeErreursSaisie, InputErrorSchema } from '@common/errors';
12
-
13
- import { EXCLURE_VALEUR } from './validators/build';
14
-
15
6
  /*----------------------------------
16
7
  - CONSTANTES
17
8
  ----------------------------------*/
@@ -61,4 +61,4 @@ md.block.ruler.after('list', 'test', (state, startLine, endLine, silent) => {
61
61
 
62
62
  }, { alt: ['paragraph', 'reference', 'blockquote'] })
63
63
 
64
- export default (markdown: string) => md.render(markdown)
64
+ export default md;
@@ -19,7 +19,7 @@ type TDetailsErreur = {
19
19
  /*----------------------------------
20
20
  - ERREURS
21
21
  ----------------------------------*/
22
- export abstract class Erreur extends Error {
22
+ export abstract class CoreError extends Error {
23
23
 
24
24
  public static msgDefaut: string;
25
25
 
@@ -38,7 +38,7 @@ export abstract class Erreur extends Error {
38
38
 
39
39
  super(message);
40
40
 
41
- this.message = message || (this.constructor as typeof Erreur).msgDefaut;
41
+ this.message = message || (this.constructor as typeof CoreError).msgDefaut;
42
42
 
43
43
  if (details !== undefined) {
44
44
  this.idRapport = details.idRapport;
@@ -66,13 +66,13 @@ export abstract class Erreur extends Error {
66
66
  }
67
67
  }
68
68
 
69
- export class InputError extends Erreur {
69
+ export class InputError extends CoreError {
70
70
  public http = 400;
71
71
  public title = "Bad Request";
72
72
  public static msgDefaut = "Bad Request.";
73
73
  }
74
74
 
75
- export class InputErrorSchema extends Erreur {
75
+ export class InputErrorSchema extends CoreError {
76
76
 
77
77
  public http = 400;
78
78
  public title = "Bad Request";
@@ -103,36 +103,40 @@ export class InputErrorSchema extends Erreur {
103
103
  }
104
104
  }
105
105
 
106
- export class AuthRequired extends Erreur {
106
+ export class AuthRequired extends CoreError {
107
107
  public http = 401;
108
108
  public title = "Authentication Required";
109
109
  public static msgDefaut = "Please Login to Continue.";
110
110
  }
111
111
 
112
- export class Forbidden extends Erreur {
112
+ export class Forbidden extends CoreError {
113
113
  public http = 403;
114
114
  public title = "Access Denied";
115
115
  public static msgDefaut = "You're not allowed to access to this resource.";
116
116
  }
117
117
 
118
- export class NotFound extends Erreur {
118
+ export class NotFound extends CoreError {
119
119
  public http = 404;
120
120
  public title = "Not Found";
121
121
  public static msgDefaut = "The resource you asked for was not found.";
122
122
  }
123
123
 
124
- export class Anomaly extends Erreur {
124
+ export class Anomaly extends CoreError {
125
125
 
126
126
  public http = 500;
127
127
  public title = "Technical Error";
128
128
  public static msgDefaut = "A technical error has occurred. A notification has just been sent to the admin.";
129
129
 
130
- public constructor(message, public data: object) {
130
+ public constructor(
131
+ message: string,
132
+ public dataForDebugging?: object,
133
+ public originalError?: Error,
134
+ ) {
131
135
  super(message);
132
136
  }
133
137
  }
134
138
 
135
- export class NotAvailable extends Erreur {
139
+ export class NotAvailable extends CoreError {
136
140
 
137
141
  // TODO: page erreur pour code 503
138
142
  public http = 404;
@@ -149,7 +153,7 @@ export const instancierViaCode = (
149
153
  code: number,
150
154
  message?: string | TListeErreursSaisie,
151
155
  details?: TDetailsErreur
152
- ): Erreur => {
156
+ ): CoreError => {
153
157
 
154
158
  if (typeof message === 'object')
155
159
  return new InputErrorSchema(message, details);
@@ -163,4 +167,4 @@ export const instancierViaCode = (
163
167
  }
164
168
  }
165
169
 
166
- export default Erreur;
170
+ export default CoreError;
@@ -4,12 +4,18 @@
4
4
 
5
5
  import type { HttpMethod } from '@server/services/router';
6
6
 
7
+ import type { FileToUpload } from '@client/components/inputv3/file';
8
+
7
9
  /*----------------------------------
8
10
  - TYPES
9
11
  ----------------------------------*/
10
12
 
11
13
  export type TFetcherList = { [id: string]: TFetcher }
12
14
 
15
+ export type TPostData = {[key: string]: PrimitiveValue}
16
+
17
+ export type TPostDataWithFile = {[key: string]: PrimitiveValue | FileToUpload}
18
+
13
19
  export type TFetcher<TData extends unknown = unknown> = {
14
20
 
15
21
  // For async calls: api.post(...).then((data) => ...)
@@ -18,20 +24,22 @@ export type TFetcher<TData extends unknown = unknown> = {
18
24
 
19
25
  method: HttpMethod,
20
26
  path: string,
21
- data?: object,
27
+ data?: TPostData,
22
28
  options?: TApiFetchOptions
23
29
  }
24
30
 
25
31
  export type TFetcherArgs = [
26
32
  method: HttpMethod,
27
33
  path: string,
28
- data?: object,
34
+ data?: TPostData,
29
35
  options?: TApiFetchOptions
30
36
  ]
31
37
 
32
38
  export type TApiFetchOptions = {
33
39
  captcha?: string, // Action id (required by recaptcha)
34
- onProgress?: (percent: number) => void
40
+ onProgress?: (percent: number) => void,
41
+ // Default: json
42
+ encoding?: 'json' | 'multipart'
35
43
  }
36
44
 
37
45
  // https://stackoverflow.com/questions/44851268/typescript-how-to-extract-the-generic-parameter-from-a-type