5htp-core 0.2.1 → 0.2.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 (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 +23 -4
  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
@@ -2,7 +2,12 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- import NormalizedFile from '@common/data/file';
5
+ // Npm
6
+ import mime from 'mime-types';
7
+
8
+ // Core
9
+ import FileToUpload from '@client/components/inputv3/file/FileToUpload';
10
+ import { InputError } from '@common/errors';
6
11
 
7
12
  /*----------------------------------
8
13
  - TYPES
@@ -11,6 +16,34 @@ import NormalizedFile from '@common/data/file';
11
16
  import type { Request, Response, NextFunction } from 'express';
12
17
  import type { FileArray, UploadedFile } from 'express-fileupload';
13
18
 
19
+ /*----------------------------------
20
+ - CONFIG
21
+ ----------------------------------*/
22
+ const reMultipart = /^multipart\/(?:form-data|related)(?:;|$)/i;
23
+
24
+ /*----------------------------------
25
+ - MIDDLEWARE
26
+ ----------------------------------*/
27
+ export const MiddlewareFormData = (req: Request, res: Response, next: NextFunction) => {
28
+
29
+ // Verif si multipart
30
+ if (!isMutipart( req ))
31
+ return next();
32
+
33
+ // Données body + fichiers
34
+ // NOTE: Les données devant obligatoirement passer par le validateur de schema,
35
+ // On peut mélanger le body et les files sans risque de sécurité
36
+ req.body = traiterMultipart(req.body, req['files']);
37
+ //req.files = traiterMultipart(req.files);
38
+
39
+ next();
40
+ }
41
+
42
+ /*----------------------------------
43
+ - FUNCTIONS
44
+ ----------------------------------*/
45
+ export const isMutipart = (req: Request) => req.headers['content-type'] && reMultipart.exec( req.headers['content-type'] );
46
+
14
47
  export const traiterMultipart = (...canaux: any[]) => {
15
48
 
16
49
  let sortie: {[nom: string]: any} = {};
@@ -20,38 +53,39 @@ export const traiterMultipart = (...canaux: any[]) => {
20
53
  if (!donnees)
21
54
  continue;
22
55
 
23
- for (const chemin in donnees) {
24
- let donnee = donnees[chemin];
56
+ for (const fieldPath in donnees) {
57
+ let donnee = donnees[fieldPath];
25
58
 
26
59
  let brancheA = sortie;
27
- const resultats = [...chemin.matchAll(/[^\[\]]+/g)];
28
- for (let iCle = 0; iCle < resultats.length; iCle++) {
60
+ const results = [...fieldPath.matchAll(/[^\[\]]+/g)];
61
+ for (let iCle = 0; iCle < results.length; iCle++) {
29
62
 
30
- const [cle] = resultats[ iCle ];
63
+ const [cle] = results[ iCle ];
31
64
 
32
- // Si ce n'est pas le dernier
33
- if (iCle !== resultats.length - 1) {
65
+ // Need to go deeper to find data
66
+ if (iCle !== results.length - 1) {
34
67
 
35
68
  if (brancheA[ cle ] === undefined) {
36
- const tableau = !isNaN( resultats[ iCle + 1 ][0] as any )
69
+ const tableau = !isNaN( results[ iCle + 1 ][0] as any )
37
70
  brancheA[ cle ] = tableau ? [] : {};
38
71
  }
39
72
 
40
73
  brancheA = brancheA[ cle ];
41
-
42
- // Donnée atteinte
43
- } else {
44
-
45
- // Fichier
46
- if (typeof donnee === 'object' && donnee.data !== undefined && donnee.data instanceof Buffer){
47
- donnee = normaliserFichier(donnee);
48
- }
49
-
50
- brancheA[ cle ] = donnee;
51
-
52
-
74
+ continue;
53
75
  }
54
76
 
77
+ // Data reached
78
+ if (
79
+ typeof donnee === 'object'
80
+ &&
81
+ donnee.data !== undefined
82
+ &&
83
+ donnee.data instanceof Buffer
84
+ ){
85
+ donnee = normalizeFile(donnee);
86
+ }
87
+
88
+ brancheA[ cle ] = donnee;
55
89
  }
56
90
  }
57
91
  }
@@ -59,27 +93,22 @@ export const traiterMultipart = (...canaux: any[]) => {
59
93
  return sortie;
60
94
  }
61
95
 
62
- const reMultipart = /^multipart\/(?:form-data|related)(?:;|$)/i;
63
- export const requeteMultipart = (req: Request) => reMultipart.exec( req.headers['content-type'] );
96
+ const normalizeFile = (file: UploadedFile) => {
64
97
 
65
- const normaliserFichier = (file: UploadedFile) => new NormalizedFile({
66
- name: file.name,
67
- type: file.mimetype,
68
- size: file.size,
69
- data: file.data,
70
- })
98
+ const ext = mime.extension(file.mimetype);
71
99
 
72
- export const MiddlewareFormData = (req: Request, res: Response, next: NextFunction) => {
100
+ if (ext === false)
101
+ throw new InputError(`We couldn't determine the type of the CV file you sent. Please encure it's not corrupted and try again.`);
73
102
 
74
- // Verif si multipart
75
- if (!requeteMultipart( req ))
76
- return next();
77
-
78
- // Données body + fichiers
79
- // NOTE: Les données devant obligatoirement passer par le validateur de schema,
80
- // On peut mélanger le body et les files sans risque de sécurité
81
- req.body = traiterMultipart(req.body, req.files);
82
- //req.files = traiterMultipart(req.files);
103
+ return new FileToUpload({
83
104
 
84
- next();
85
- }
105
+ name: file.name,
106
+ type: file.mimetype,
107
+ size: file.size,
108
+
109
+ data: file.data,
110
+
111
+ md5: file.md5,
112
+ ext: ext
113
+ })
114
+ }
@@ -9,15 +9,19 @@
9
9
  - DEPENDANCES
10
10
  ----------------------------------*/
11
11
 
12
+ // Node
13
+ import path from 'path';
14
+
12
15
  // Npm
13
16
  import type express from 'express';
14
17
  import { v4 as uuid } from 'uuid';
18
+ import fs from 'fs-extra';
15
19
  import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
16
20
 
17
21
  // Core
18
22
  import Application, { Service } from '@server/app';
19
23
  import context from '@server/context';
20
- import { Erreur, NotFound } from '@common/errors';
24
+ import { CoreError, NotFound } from '@common/errors';
21
25
  import BaseRouter, {
22
26
  TRoute, TErrorRoute, TRouteModule,
23
27
  TRouteOptions, defaultOptions
@@ -42,7 +46,7 @@ import DocumentRenderer from './response/page/document';
42
46
 
43
47
  export { default as RouterService } from './service';
44
48
  export { default as RequestService } from './request/service';
45
- export type { default as Request } from "./request";
49
+ export type { default as Request, UploadedFile } from "./request";
46
50
  export type { default as Response, TRouterContext } from "./response";
47
51
  export type { TRoute } from '@common/router';
48
52
 
@@ -168,6 +172,7 @@ export default class ServerRouter<
168
172
  }
169
173
 
170
174
  private registerRoutes(defModules: GlobImportedWithMetas<TRouteModule>) {
175
+
171
176
  for (const routeModule of defModules) {
172
177
 
173
178
  const register = routeModule.exports.__register;
@@ -181,6 +186,14 @@ export default class ServerRouter<
181
186
  this.afterRegister();
182
187
  }
183
188
 
189
+ // TODO: Generate TS type of the routes list
190
+ public url<TRoutePath extends keyof Routes = keyof Routes>(
191
+ path: TRoutePath,
192
+ params: Routes[TRoutePath]["params"]
193
+ ) {
194
+ return this.http.publicUrl + path;
195
+ }
196
+
184
197
  /*----------------------------------
185
198
  - REGISTER
186
199
  ----------------------------------*/
@@ -265,9 +278,12 @@ export default class ServerRouter<
265
278
  console.info("Pre-Loading request services");
266
279
  //await TrackingService.LoadCache();
267
280
 
268
- console.info("Loading routes ...");
281
+ // Generate typescript typings
282
+ if (this.app.env.profile = 'dev')
283
+ this.genTypings();
269
284
 
270
285
  // Ordonne par ordre de priorité
286
+ console.info("Loading routes ...");
271
287
  this.routes.sort((r1, r2) => {
272
288
 
273
289
  const prioDelta = r2.options.priority - r1.options.priority;
@@ -329,6 +345,21 @@ export default class ServerRouter<
329
345
  console.info(this.routes.length + " routes where registered.");
330
346
  }
331
347
 
348
+ private genTypings() {
349
+ fs.outputFileSync( path.join(this.app.path.typings, 'routes.d.ts'), `
350
+ declare type Routes = {
351
+ ${this.routes.map( route => `
352
+ '${route.path}': {
353
+ params: {
354
+ ${route.keys.map( k => "'" + k + "': string").join(',\n')}
355
+ }
356
+ }
357
+ `).join(',')}
358
+ }
359
+ }
360
+ `);
361
+ }
362
+
332
363
  /*----------------------------------
333
364
  - RESOLUTION
334
365
  ----------------------------------*/
@@ -499,7 +530,7 @@ export default class ServerRouter<
499
530
  request.res.json(responseData);
500
531
  }
501
532
 
502
- private async handleError(e: Erreur, request: ServerRequest<ServerRouter>) {
533
+ private async handleError(e: CoreError, request: ServerRequest<ServerRouter>) {
503
534
 
504
535
  const code = 'http' in e ? e.http : 500;
505
536
  const route = this.errors[code];
@@ -10,22 +10,24 @@ import Bowser from "bowser";
10
10
 
11
11
  // Core
12
12
  import BaseRequest from '@common/router/request';
13
+ import type FileToUpload from '@client/components/inputv3/file/FileToUpload';
13
14
 
14
15
  // Specific
15
- import ServerResponse from '../response';
16
+ import type {
17
+ default as Router, Config as RouterConfig,
18
+ HttpMethod, HttpHeaders
19
+ } from '..';
16
20
  import ApiClient from './api';
21
+ import ServerResponse from '../response';
17
22
 
18
23
  /*----------------------------------
19
24
  - TYPES
20
25
  ----------------------------------*/
21
26
 
22
- import type {
23
- default as Router, Config as RouterConfig,
24
- HttpMethod, HttpHeaders
25
- } from '@server/services/router';
26
-
27
27
  const localeFilter = (input: any) => typeof input === 'string' && ISO6391.validate(input) ? input : undefined;
28
28
 
29
+ export type UploadedFile = With<FileToUpload, 'md5'|'ext'>
30
+
29
31
  /*----------------------------------
30
32
  - CONTEXTE
31
33
  ----------------------------------*/
@@ -9,7 +9,7 @@ import SchemaValidator, { TFileValidator } from '@common/validation/validators';
9
9
 
10
10
  import Validator, { EXCLUDE_VALUE,} from '@common/validation/validator';
11
11
 
12
- import NormalizedFile from '@common/data/file';
12
+ import type FileToUpload from '@client/components/inputv3/file/FileToUpload';
13
13
 
14
14
  /*----------------------------------
15
15
  - TYPES
@@ -21,8 +21,8 @@ import NormalizedFile from '@common/data/file';
21
21
  ----------------------------------*/
22
22
  export default class ServerSchemaValidator extends SchemaValidator {
23
23
 
24
- public file = ({ ...opts }: TFileValidator & { sharp: any }) =>
25
- new Validator<NormalizedFile>('file', (val, input, output) => {
24
+ public file = ({ ...opts }: TFileValidator) =>
25
+ new Validator<FileToUpload>('file', (val, input, output) => {
26
26
 
27
27
  // Chaine = url ancien fichier = exclusion de la valeur pour conserver l'ancien fichier
28
28
  // NOTE: Si la valeur est présente mais undefined, alors on supprimera le fichier
@@ -33,14 +33,7 @@ export default class ServerSchemaValidator extends SchemaValidator {
33
33
  const file = this.validateFile(opts, val, input, output);
34
34
 
35
35
  if (file === undefined)
36
- return file;
37
-
38
- // Process Image
39
- if (opts.sharp !== undefined) {
40
-
41
-
42
-
43
- }
36
+ return EXCLUDE_VALUE;
44
37
 
45
38
  return file;
46
39
  }, opts)
@@ -7,14 +7,21 @@ import {
7
7
  default as Router, RequestService, Request as ServerRequest
8
8
  } from '@server/services/router';
9
9
 
10
- import ServerSchemaValidator from '.';
11
-
12
10
  import Schema, { TSchemaFields, TValidatedData } from '@common/validation/schema';
13
11
 
12
+ // Specific
13
+ import ServerSchemaValidator from '.';
14
+
14
15
  /*----------------------------------
15
- - TYPES
16
+ - SERVICE CONFIG
16
17
  ----------------------------------*/
17
18
 
19
+ const LogPrefix = `[router][validation]`;
20
+
21
+ export type TConfig = {
22
+ debug?: boolean
23
+ }
24
+
18
25
  /*----------------------------------
19
26
  - SERVICE
20
27
  ----------------------------------*/
@@ -22,6 +29,7 @@ export default class RequestValidator extends ServerSchemaValidator implements R
22
29
 
23
30
  public constructor(
24
31
  public request: ServerRequest<Router>,
32
+ public config: TConfig,
25
33
  public router = request.router,
26
34
  public app = router.app
27
35
  ) {
@@ -32,7 +40,7 @@ export default class RequestValidator extends ServerSchemaValidator implements R
32
40
 
33
41
  public validate<TSchemaFieldsA extends TSchemaFields>( fields: TSchemaFieldsA ): TValidatedData<TSchemaFieldsA> {
34
42
 
35
- console.log("Validate request data:", this.request.data);
43
+ this.config.debug && console.log(LogPrefix, "Validate request data:", this.request.data);
36
44
 
37
45
  const schema = new Schema(fields);
38
46
 
@@ -42,9 +50,10 @@ export default class RequestValidator extends ServerSchemaValidator implements R
42
50
  this.request.data,
43
51
  {},
44
52
  {
45
- critique: true,
46
- validationComplete: true,
47
- avecDependances: false
53
+ debug: this.config.debug,
54
+ throwError: true,
55
+ validateAll: true,
56
+ validateDeps: false
48
57
  },
49
58
  []
50
59
  );
@@ -8,7 +8,7 @@ import {
8
8
  RouterService
9
9
  } from '@server/services/router';
10
10
 
11
- import RequestValidator from './request';
11
+ import RequestValidator, { TConfig } from './request';
12
12
 
13
13
  /*----------------------------------
14
14
  - TYPES
@@ -23,11 +23,15 @@ export default class AuthenticationRouterService<
23
23
  TUser extends {} = {}
24
24
  > extends RouterService {
25
25
 
26
+ public constructor( protected config: TConfig ) {
27
+ super();
28
+ }
29
+
26
30
  public async register() {
27
31
 
28
32
  }
29
33
 
30
34
  public requestService( request: ServerRequest< TRouterWithSchema<this>> ): RequestValidator {
31
- return new RequestValidator( request );
35
+ return new RequestValidator( request, this.config );
32
36
  }
33
37
  }
@@ -6,38 +6,61 @@
6
6
  import crypto from 'crypto';
7
7
 
8
8
  // Core
9
+ import Application, { Service } from '@server/app';
9
10
  import { Forbidden } from '@common/errors';
10
11
 
11
- const debug = true;
12
-
13
12
  /*----------------------------------
14
13
  - CONFIG
15
14
  ----------------------------------*/
16
15
 
17
- const ENC_KEY = "bf3c199c2470cb477d907b1e0917c17b"; // set random encryption key
18
- const IV = "5183666c72eec9e4"; // set random initialisation vector
16
+
17
+ /*----------------------------------
18
+ - SERVICE CONFIG
19
+ ----------------------------------*/
20
+
21
+ export type Config = {
22
+ debug?: boolean,
23
+ iv: string,
24
+ keys: {[keyName: string]: string}
25
+ }
26
+
27
+ export type Hooks = {
28
+
29
+ }
19
30
 
20
31
  /*----------------------------------
21
32
  - SERVICE
22
33
  ----------------------------------*/
23
- class AES {
34
+ export default class AES<TConfig extends Config = Config> extends Service<TConfig, Hooks, Application> {
24
35
 
25
- public encrypt( data: any ) {
36
+ public async register() {
37
+
38
+ }
39
+
40
+ public async start() {
41
+
42
+ }
43
+
44
+ public encrypt( keyName: keyof TConfig["keys"], data: any ) {
45
+
46
+ const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
26
47
 
27
48
  data = JSON.stringify(data);
28
49
 
29
- let cipher = crypto.createCipheriv('aes-256-cbc', ENC_KEY, IV);
50
+ let cipher = crypto.createCipheriv('aes-256-cbc', encKey, this.config.iv);
30
51
  let encrypted = cipher.update(data, 'utf8', 'base64');
31
52
  encrypted += cipher.final('base64');
32
53
  return encrypted;
33
54
 
34
55
  }
35
56
 
36
- public decrypt( data: string ) {
57
+ public decrypt( keyName: keyof TConfig["keys"], data: string ) {
58
+
59
+ const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
37
60
 
38
61
  try {
39
62
 
40
- let decipher = crypto.createDecipheriv('aes-256-cbc', ENC_KEY, IV);
63
+ let decipher = crypto.createDecipheriv('aes-256-cbc', encKey, this.config.iv);
41
64
  let decrypted = decipher.update(data, 'base64', 'utf8');
42
65
  return JSON.parse(decrypted + decipher.final('utf8'));
43
66
 
@@ -46,9 +69,5 @@ class AES {
46
69
  throw new Forbidden("Invalid token.");
47
70
 
48
71
  }
49
-
50
72
  }
51
-
52
- }
53
-
54
- export default new AES;
73
+ }
@@ -79,7 +79,7 @@ export default abstract class UsersManagementService<
79
79
  public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
80
80
  public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser>;
81
81
 
82
- protected abstract displayName(user: TUser): string;
82
+ protected abstract displayName(user?: TUser | null): string;
83
83
  protected abstract displaySessionName(session: TJwtSession): string;
84
84
 
85
85
  public async decode( req: THttpRequest, withData: true ): Promise<TUser | null>;
@@ -118,7 +118,7 @@ export default abstract class UsersManagementService<
118
118
  // Deserialize full user data
119
119
  this.config.debug && console.log(LogPrefix, `Deserialize user ${sessionName}`);
120
120
  const user = await this.decodeSession(session, req);
121
- this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, user);
121
+ this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, this.displayName(user));
122
122
 
123
123
  return user;
124
124
  }
@@ -134,7 +134,7 @@ export default abstract class UsersManagementService<
134
134
  return null;
135
135
  }
136
136
 
137
- protected createSession( session: TJwtSession, request: TRequest ): string {
137
+ public createSession( session: TJwtSession, request: TRequest ): string {
138
138
 
139
139
  this.config.debug && console.info(LogPrefix, `Creating new session:`, session);
140
140
 
@@ -52,8 +52,6 @@ export default class AuthenticationRouterService<
52
52
  // TODO: Typings. (context.user ?)
53
53
  const decoded = await this.users.decode( request.req, true);
54
54
 
55
- console.log("DECODED", decoded);
56
-
57
55
  request.user = decoded || null;
58
56
  })
59
57
 
@@ -43,4 +43,14 @@ declare type TStats<T> = {
43
43
  interface IntrinsicElements {
44
44
  i: { src: TIcons } & React.HTMLAttributes<HTMLElement>;
45
45
  }
46
- }*/
46
+ }*/
47
+
48
+ declare type Routes = {
49
+ [path: string]: {
50
+ params: {
51
+ [param: string]: any
52
+ }
53
+ }
54
+ }
55
+
56
+ declare type PrimitiveValue = string | number | boolean;
@@ -9,6 +9,9 @@
9
9
  "allowJs": true,
10
10
  "strict": false,
11
11
  "downlevelIteration": true,
12
+ // Force case sensitive import filenames on Window and Mac
13
+ // https://briandesousa.net/?p=870
14
+ "forceConsistentCasingInFileNames": true,
12
15
 
13
16
  // Equivalent webpack: resolve.symblinks = false
14
17
  "preserveSymlinks": true,
@@ -1,57 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- import React from 'react';
6
- import Champ from './Base';
7
-
8
- import TextareaAutosize from 'react-textarea-autosize';
9
-
10
- /*----------------------------------
11
- - TYPES
12
- ----------------------------------*/
13
- type TValeur = string;
14
- const valeurDefaut = '' as string;
15
- type TValeurDefaut = typeof valeurDefaut;
16
- type TValeurOut = string;
17
-
18
- export type Props = {
19
- valeur: TValeur,
20
- onPressEnter?: (valeur: TValeur) => void,
21
- autoFocus?: boolean,
22
- }
23
-
24
- /*----------------------------------
25
- - COMPOSANTS
26
- ----------------------------------*/
27
- export default Champ<Props, TValeurDefaut, TValeurOut>('textarea', { valeurDefaut, saisieManuelle: true }, ({
28
- onPressEnter, attrsChamp
29
- }, { valeur, state, setState }, rendre) => {
30
-
31
- if (onPressEnter)
32
- attrsChamp.onKeyDown = (e: KeyboardEvent) => {
33
- if (e.key === 'Enter') {
34
-
35
- // Entrée seulement = envoi
36
- if (!e.shiftKey) {
37
- onPressEnter( valeur );
38
- }
39
-
40
- // Nouvelle ligne si shift key + valeur ok
41
- if (!(e.shiftKey && valeur)) {
42
- //e.stopPropagation();
43
- e.preventDefault();
44
- return false;
45
- }
46
- }
47
- }
48
-
49
- return rendre((
50
- <TextareaAutosize {...attrsChamp}
51
- value={valeur}
52
- onChange={(e: any) => {
53
- setState({ valeur: e.target.value });
54
- }}
55
- />
56
- ), { });
57
- })
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
-
3
- export default () => {
4
- return <span>coucou</span>
5
- }