5htp-core 0.4.6 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.4.6",
4
+ "version": "0.4.7",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -1,5 +1,6 @@
1
1
  .table {
2
2
  overflow: auto;
3
+ max-height: 90vh;
3
4
 
4
5
  > table {
5
6
  border-collapse: collapse;
@@ -13,7 +14,7 @@
13
14
  }
14
15
 
15
16
  &.card {
16
- padding: 1em 0;
17
+ padding: 0;
17
18
  }
18
19
  }
19
20
 
@@ -26,7 +27,7 @@ table {
26
27
 
27
28
  // By default, chrome disables text inherits
28
29
  line-height: inherit;
29
- font-size: inherit;
30
+ font-size: 0.9em;
30
31
 
31
32
  th {
32
33
  font-weight: 500;
@@ -38,8 +39,8 @@ table {
38
39
  padding: 1em 1em;
39
40
  text-align: left;
40
41
 
41
- + td, th {
42
- border-left: solid 1px #F5F5F5
42
+ &:not(:last-child) {
43
+ border-right: solid 1px #F5F5F5;
43
44
  }
44
45
 
45
46
  &:first-child {
@@ -50,6 +51,29 @@ table {
50
51
  padding-right: 2em;
51
52
  text-align: right;
52
53
  }
54
+
55
+ &.stickyColumn {
56
+ position: sticky;
57
+ background: var(--cBg);
58
+ white-space: break-spaces;
59
+ z-index: 1;
60
+
61
+ &:first-child {
62
+ left: 0;
63
+ }
64
+
65
+ &:last-child {
66
+ right: 0;
67
+ }
68
+ }
69
+ }
70
+
71
+ thead {
72
+ position: sticky;
73
+ top: 0;
74
+ background: var(--cBg);
75
+ white-space: break-spaces;
76
+ z-index: 5;
53
77
  }
54
78
 
55
79
  tbody {
@@ -57,11 +81,45 @@ table {
57
81
  td, th {
58
82
  vertical-align: middle;
59
83
  border-top: solid 1px var(--cLine);
84
+ position: relative;
85
+ }
86
+
87
+ // Rows: Crop when too long
88
+ td {
89
+
90
+ cursor: default;
91
+
92
+ &.extendable > .row {
93
+
94
+ max-width: 20em;
95
+ overflow: hidden;
96
+ justify-content: flex-start;
97
+
98
+ &::after {
99
+ content: ' ';
100
+ display: block;
101
+ position: absolute;
102
+
103
+ top: 0;
104
+ right: 0;
105
+ width: 30%;
106
+ height: 100%;
107
+
108
+ background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--cBg));
109
+ }
110
+
111
+ > * {
112
+ flex-shrink: 0;
113
+ }
114
+
115
+ > .badge {
116
+ font-size: 0.8em;
117
+ }
118
+ }
60
119
  }
61
120
 
62
- &.actuel td {
63
- background: var(--cPrincipale);
64
- color: #fff;
121
+ tr:hover > td {
122
+ background: #FAFAFA;
65
123
  }
66
124
  }
67
125
 
@@ -112,4 +170,9 @@ table {
112
170
  }
113
171
  }
114
172
  }*/
173
+ }
174
+
175
+ .modal .tableCellExtended .row {
176
+ flex-wrap: wrap;
177
+ justify-content: flex-start;
115
178
  }
@@ -2,11 +2,13 @@
2
2
  /*----------------------------------
3
3
  - DEPENDANCES
4
4
  ----------------------------------*/
5
+
5
6
  // Libs
6
7
  import React from 'react';
7
- import { ComponentChild } from 'preact';
8
+ import { JSX, ComponentChild } from 'preact';
8
9
 
9
10
  // Composants
11
+ import useContext from '@/client/context';
10
12
  import Button, { Props as TButtonProps } from '@client/components/button';
11
13
  import Popover from '../containers/Popover';
12
14
  import Checkbox from '../inputv3/Checkbox';
@@ -21,6 +23,7 @@ export type Props<TRow> = {
21
23
 
22
24
  data: TRow[],
23
25
  columns: (row: TRow, rows: TRow[], index: number) => TColumn[];
26
+ stickyHeader?: boolean,
24
27
 
25
28
  setData?: (rows: TRow[]) => void,
26
29
  empty?: ComponentChild | false,
@@ -29,11 +32,11 @@ export type Props<TRow> = {
29
32
  actions?: TAction<TRow>[]
30
33
  }
31
34
 
32
- export type TColumn = {
35
+ export type TColumn = JSX.HTMLAttributes<HTMLElement> & {
33
36
  label: ComponentChild,
34
37
  cell: ComponentChild,
35
38
  raw?: number | string | boolean,
36
- class?: string
39
+ stick?: boolean,
37
40
  }
38
41
 
39
42
  export type TAction<TRow> = Omit<TButtonProps, 'onClick'> & {
@@ -47,13 +50,16 @@ export type TAction<TRow> = Omit<TButtonProps, 'onClick'> & {
47
50
  - COMPOSANTS
48
51
  ----------------------------------*/
49
52
  export default function Liste<TRow extends TDonneeInconnue>({
53
+ stickyHeader,
50
54
  data: rows, setData, empty,
51
55
  columns, actions, ...props
52
56
  }: Props<TRow>) {
53
57
 
58
+ const { modal } = useContext();
59
+
54
60
  if (rows.length === 0)
55
61
  return empty === false ? null : (
56
- <div class="pd-2 col al-center">
62
+ <div class={"pd-2 col al-center " + (props.className || '')}>
57
63
  {empty || <>
58
64
  <i src="meh-rolling-eyes" class="xl" />
59
65
  Uh ... No rows here.
@@ -92,29 +98,75 @@ export default function Liste<TRow extends TDonneeInconnue>({
92
98
  </td>
93
99
  )}
94
100
 
95
- {columns(row, rows, iDonnee).map((col) => {
101
+ {columns(row, rows, iDonnee).map(({
102
+ label, cell, class: className, raw,
103
+ stick, width, ...cellProps
104
+ }) => {
105
+
106
+ let classe = className || '';
107
+ if (typeof raw === 'number')
108
+ classe += 'txtRight';
109
+
110
+ if (stick) {
111
+ classe += ' stickyColumn';
112
+ }
113
+
114
+ if (width) {
115
+
116
+ if (cellProps.style === undefined)
117
+ cellProps.style = {};
118
+
119
+ cellProps.style = {
120
+ ...cellProps.style,
121
+ minWidth: width,
122
+ width: width,
123
+ maxWidth: width,
124
+ }
125
+ }
96
126
 
97
127
  if (iDonnee === 0) renduColonnes.push(
98
- <th>
99
- {col.label}
128
+ <th class={classe} {...cellProps}>
129
+ {label}
100
130
  </th>
101
131
  );
102
132
 
103
- const affichageBrut = ['number', 'string'].includes(typeof col.cell) || React.isValidElement(col.cell);
133
+ let render: ComponentChild;
134
+ if (Array.isArray(cell)) {
104
135
 
105
- let classe = col.class || '';
106
- if (typeof col.raw === 'number')
107
- classe += 'txtRight';
136
+ classe += ' extendable';
137
+
138
+ render = (
139
+ <div class="row sp-05">
140
+ {cell.map((item, i) => (
141
+ <span class={"badge bg light" + ((i % 7) + 1)}>
142
+ {item}
143
+ </span>
144
+ ))}
145
+ </div>
146
+ )
147
+
148
+ // Extension
149
+ cellProps.onClick = () => modal.show(() => (
150
+ <div class="card col tableCellExtended">
151
+ <h3>{label}</h3>
152
+ {render}
153
+ </div>
154
+ ));
155
+
156
+ } else if (['number', 'string'].includes(typeof cell) || React.isValidElement(cell)) {
157
+ render = cell;
158
+ } else
159
+ render = JSON.stringify(cell);
108
160
 
109
161
  return (
110
- <td class={classe}>
111
- {affichageBrut ? col.cell : JSON.stringify(col.cell)}
162
+ <td class={classe} {...cellProps}>
163
+ {render}
112
164
  </td>
113
165
  )
114
166
  })}
115
167
 
116
168
  {actions !== undefined && (
117
- <td>
169
+ <td class="stickyColumn">
118
170
  <Popover content={(
119
171
  <ul class="col menu card bg white">
120
172
  {actions.map(({ label, onClick, ...props }: TAction<TRow>) => (
@@ -148,7 +200,7 @@ export default function Liste<TRow extends TDonneeInconnue>({
148
200
  return <>
149
201
  <div {...props}>
150
202
  <table>
151
- <thead>
203
+ <thead className={stickyHeader ? 'stickyHeader' : undefined}>
152
204
  <tr>
153
205
  {selectionMultiple && (
154
206
  <th>
@@ -5,6 +5,9 @@
5
5
  // Core
6
6
  import Response from '../response';
7
7
 
8
+ // Types
9
+ import type { TBasicUser } from '@server/services/auth';
10
+
8
11
  /*----------------------------------
9
12
  - TYPES
10
13
  ----------------------------------*/
@@ -22,7 +25,7 @@ export default abstract class BaseRequest {
22
25
 
23
26
  public data: TObjetDonnees = {};
24
27
  public abstract response?: Response;
25
- public user: User | null = null;
28
+ public user: TBasicUser | null = null;
26
29
 
27
30
  public constructor(
28
31
  public path: string,
@@ -41,6 +41,34 @@ type TSubtype = TSchemaSubtype | Validator<any>;
41
41
  ----------------------------------*/
42
42
  export default class SchemaValidators {
43
43
 
44
+ /*----------------------------------
45
+ - UTILITIES
46
+ ----------------------------------*/
47
+ // Make every field optional
48
+ public partial = <TFields extends TSchemaFields>(schema: TFields, fieldsList?: (keyof TFields)[] ) => {
49
+
50
+ if (fieldsList === undefined)
51
+ fieldsList = Object.keys(schema) as (keyof TFields)[];
52
+
53
+ const partialSchema: Partial<TFields> = {};
54
+ for (const key of fieldsList) {
55
+
56
+ if (!(key in schema))
57
+ throw new Error("The field " + key + " is not in the schema.");
58
+
59
+ // Only if validator
60
+ if (schema[key] instanceof Validator)
61
+ partialSchema[key] = new Validator(schema[key].type, schema[key].validateType, {
62
+ ...schema[key].options,
63
+ opt: true
64
+ });
65
+ else
66
+ partialSchema[key] = schema[key];
67
+ }
68
+
69
+ return partialSchema as TFields;
70
+ }
71
+
44
72
  /*----------------------------------
45
73
  - CONTENEURS
46
74
  ----------------------------------*/
@@ -37,17 +37,6 @@ type Hooks = {
37
37
  }
38
38
  }
39
39
 
40
- declare global {
41
-
42
- //interface Services { }
43
-
44
- interface AppHooks {
45
-
46
- }
47
-
48
- interface User { }
49
- }
50
-
51
40
  export const Service = ServicesContainer;
52
41
 
53
42
  /*----------------------------------
@@ -62,13 +62,24 @@ export type TServices = {
62
62
 
63
63
  }
64
64
 
65
+ export type TBasicUser = {
66
+ type: string,
67
+ name: string,
68
+ roles: string[]
69
+ }
70
+
71
+ export type TBasicJwtSession = {
72
+ accountType: string,
73
+ apiKey?: string
74
+ }
75
+
65
76
  /*----------------------------------
66
77
  - SERVICE
67
78
  ----------------------------------*/
68
79
  export default abstract class AuthService<
69
- TUser extends {},
80
+ TUser extends TBasicUser,
70
81
  TApplication extends Application,
71
- TJwtSession extends {} = {},
82
+ TJwtSession extends TBasicJwtSession = TBasicJwtSession,
72
83
  TRequest extends ServerRequest<Router> = ServerRequest<Router>,
73
84
  > extends Service<TConfig, THooks, TApplication, TServices> {
74
85
 
@@ -95,51 +106,37 @@ export default abstract class AuthService<
95
106
  public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
96
107
  public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser | null>;
97
108
 
98
- protected abstract displayName(user?: TUser | null): string;
99
109
  protected abstract displaySessionName(session: TJwtSession): string;
100
110
 
111
+ // https://beeceptor.com/docs/concepts/authorization-header/#examples
101
112
  public async decode( req: THttpRequest, withData: true ): Promise<TUser | null>;
102
113
  public async decode( req: THttpRequest, withData?: false ): Promise<TJwtSession | null>;
103
114
  public async decode( req: THttpRequest, withData: boolean = false ): Promise<TJwtSession | TUser | null> {
104
115
 
105
116
  this.config.debug && console.log(LogPrefix, 'Decode:', { cookie: req.cookies['authorization'] });
106
117
 
107
- let token: string | undefined;
108
- if (('cookies' in req) && typeof req.cookies['authorization'] === 'string')
109
- token = req.cookies['authorization'];
110
- // Desktop app webview do not support cookie config, so wwe retrieve it from headers
111
- else if (typeof req.headers['authorization'] === 'string')
112
- token = req.headers['authorization'];
118
+ // Get auth token
119
+ const authMethod = this.getAuthMethod(req);
120
+ if (authMethod === null)
121
+ return null;
122
+ const { tokenType, token } = authMethod;
113
123
 
114
- if (token === undefined)
115
- return this.unauthorized(req);
116
-
117
- let session: TJwtSession;
118
- try {
119
- session = jwt.verify(token, this.config.jwt.key, {
120
- maxAge: this.config.jwt.expiration
121
- });
122
- } catch (error) {
123
- console.warn(LogPrefix, "Failed to decode jwt token:", token);
124
- return this.unauthorized(req);
125
- }
124
+ // Get auth session
125
+ const session = this.getAuthSession(tokenType, token);
126
126
 
127
127
  // Return email only
128
- const sessionName = this.displaySessionName(session);
129
128
  if (!withData) {
130
- this.config.debug && console.log(LogPrefix, `Auth user ${sessionName} successfull. Return email only`);
129
+ this.config.debug && console.log(LogPrefix, `Auth user successfull. Return email only`);
131
130
  return session;
132
131
  }
133
132
 
134
133
  // Deserialize full user data
135
- this.config.debug && console.log(LogPrefix, `Deserialize user ${sessionName}`);
134
+ this.config.debug && console.log(LogPrefix, `Deserialize user`, session);
136
135
  const user = await this.decodeSession(session, req);
137
-
138
- // User not found
139
136
  if (user === null)
140
137
  return null;
141
138
 
142
- this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, this.displayName(user));
139
+ this.config.debug && console.log(LogPrefix, `Deserialized user:`, user.name);
143
140
 
144
141
  return {
145
142
  ...user,
@@ -147,15 +144,55 @@ export default abstract class AuthService<
147
144
  };
148
145
  }
149
146
 
150
- public unauthorized( req: THttpRequest ) {
147
+ private getAuthMethod( req: THttpRequest ): null | { token: string, tokenType?: string } {
151
148
 
152
- if ('res' in req) {
153
- // If use auth failed, we remove the jwt token so we avoid to trigger the same auth error in the next request
154
- console.warn(LogPrefix, "Auth failed: remove authorization cookie");
155
- req.res?.clearCookie('authorization');
156
- }
149
+ let token: string | undefined;
150
+ let tokenType: string | undefined;
151
+ if (typeof req.headers['authorization'] === 'string') {
152
+
153
+ ([ tokenType, token ] = req.headers['authorization'].split(' '));
157
154
 
158
- return null;
155
+ } else if (('cookies' in req) && typeof req.cookies['authorization'] === 'string') {
156
+
157
+ token = req.cookies['authorization'];
158
+ tokenType = 'Bearer';
159
+
160
+ } else
161
+ return null;
162
+
163
+ if (token === undefined)
164
+ return null;
165
+
166
+ return { tokenType, token };
167
+ }
168
+
169
+ private getAuthSession( tokenType: string | undefined, token: string ): TJwtSession {
170
+
171
+ let session: TJwtSession;
172
+
173
+ // API Key
174
+ if (tokenType === 'Apikey') {
175
+
176
+ const [accountType] = token.split('-');
177
+
178
+ this.config.debug && console.log(LogPrefix, `Auth via API Key`, token);
179
+ session = { accountType, apiKey: token } as TJwtSession;
180
+
181
+ // JWT
182
+ } else if (tokenType === 'Bearer') {
183
+ this.config.debug && console.log(LogPrefix, `Auth via JWT token`, token);
184
+ try {
185
+ session = jwt.verify(token, this.config.jwt.key, {
186
+ maxAge: this.config.jwt.expiration
187
+ });
188
+ } catch (error) {
189
+ console.warn(LogPrefix, "Failed to decode jwt token:", token);
190
+ throw new Forbidden(`The JWT token provided in the Authorization header is invalid`);
191
+ }
192
+ } else
193
+ throw new InputError(`The authorization scheme provided in the Authorization header is unsupported.`);
194
+
195
+ return session;
159
196
  }
160
197
 
161
198
  public createSession( session: TJwtSession, request: TRequest ): string {
@@ -176,27 +213,24 @@ export default abstract class AuthService<
176
213
  const user = request.user;
177
214
  if (!user) return;
178
215
 
179
- this.config.debug && console.info(LogPrefix, `Logout ${this.displayName(user)}`);
216
+ this.config.debug && console.info(LogPrefix, `Logout ${user.name}`);
180
217
  request.res.clearCookie('authorization');
181
218
  }
182
219
 
183
- public check( request: TRequest, role: TUserRole, motivation?: string): TUser;
184
- public check( request: TRequest, role: false, motivation?: string): null;
185
- public check( request: TRequest, role: TUserRole | boolean = 'USER', motivation?: string): TUser | null {
220
+ public check( request: TRequest, entity: string, role: TUserRole, motivation?: string): TUser;
221
+ public check( request: TRequest, entity: string, role: false, motivation?: string): null;
222
+ public check( request: TRequest, entity: string, role: TUserRole | false = 'USER', motivation?: string): TUser | null {
186
223
 
187
224
  const user = request.user;
188
225
 
189
- this.config.debug && console.warn(LogPrefix, `Check auth, role = ${role}. Current user =`, this.displayName(user));
226
+ this.config.debug && console.warn(LogPrefix, `Check auth, role = ${role}. Current user =`, user?.name);
227
+
228
+ console.log({ entity, role, motivation });
190
229
 
191
230
  if (user === undefined) {
192
231
 
193
232
  throw new Error(`request.user has not been decoded.`);
194
233
 
195
- // Shortcut: { auth: true } <=> { auth: 'USER' }
196
- } else if (role === true) {
197
-
198
- role = 'USER';
199
-
200
234
  // No auth needed
201
235
  } else if (role === false) {
202
236
 
@@ -206,18 +240,23 @@ export default abstract class AuthService<
206
240
  } else if (user === null) {
207
241
 
208
242
  this.config.debug && console.warn(LogPrefix, "Refusé pour anonyme (" + request.ip + ")");
209
- throw new AuthRequired(motivation);
243
+ throw new AuthRequired('Please login to continue');
244
+
245
+ } else if (user.type !== entity) {
246
+
247
+ this.config.debug && console.warn(LogPrefix, `User type mismatch: ${user.type} (user) vs ${entity} (expected) (${request.ip})`);
248
+ throw new AuthRequired("Your account type doesn't have access to the requested content.");
210
249
 
211
250
  // Insufficient permissions
212
251
  } else if (!user.roles.includes(role)) {
213
252
 
214
- console.warn(LogPrefix, "Refusé: " + role + " pour " + this.displayName(user) + " (" + (user.roles ? user.roles.join(', ') : 'role inconnu') + ")");
253
+ console.warn(LogPrefix, "Refusé: " + role + " pour " + user.name + " (" + (user.roles ? user.roles.join(', ') : 'role inconnu') + ")");
215
254
 
216
255
  throw new Forbidden("You do not have sufficient permissions to access this resource.");
217
256
 
218
257
  } else {
219
258
 
220
- console.warn(LogPrefix, "Autorisé " + role + " pour " + this.displayName(user) + " (" + user.roles.join(', ') + ")");
259
+ console.warn(LogPrefix, "Autorisé " + role + " pour " + user.name + " (" + user.roles.join(', ') + ")");
221
260
 
222
261
  }
223
262
 
@@ -14,6 +14,9 @@ import { InputError, AuthRequired, Forbidden } from '@common/errors';
14
14
  import type AuthenticationRouterService from '.';
15
15
  import type { default as UsersManagementService, TUserRole } from '..';
16
16
 
17
+ // Types
18
+ import type { TBasicUser } from '@server/services/auth';
19
+
17
20
  /*----------------------------------
18
21
  - TYPES
19
22
  ----------------------------------*/
@@ -22,7 +25,7 @@ import type { default as UsersManagementService, TUserRole } from '..';
22
25
  - MODULE
23
26
  ----------------------------------*/
24
27
  export default class UsersRequestService<
25
- TUser extends {}
28
+ TUser extends TBasicUser
26
29
  > extends RequestService {
27
30
 
28
31
  public constructor(
@@ -41,9 +44,10 @@ export default class UsersRequestService<
41
44
  return this.users.logout( this.request );
42
45
  }
43
46
 
44
- public check( role: TUserRole, motivation?: string): TUser;
45
- public check( role: false, motivation?: string): null;
46
- public check( role: TUserRole | boolean = 'USER', motivation?: string): TUser | null {
47
- return this.users.check( this.request, role, motivation );
47
+ // TODO: return user type according to entity
48
+ public check( entity: string, role: TUserRole, motivation?: string): TUser;
49
+ public check( entity: string, role: false, motivation?: string): null;
50
+ public check( entity: string, role: TUserRole | boolean = 'USER', motivation?: string): TUser | null {
51
+ return this.users.check( this.request, entity, role, motivation );
48
52
  }
49
53
  }
@@ -551,7 +551,7 @@ export default class SQL extends Service<Config, Hooks, Application, Services> {
551
551
  if (updateAll) {
552
552
  for (const record of data)
553
553
  for (const key in record)
554
- if (!valuesNamesToUpdate.includes( key ))
554
+ if (!valuesNamesToUpdate.includes( key ) && (key in table.colonnes))
555
555
  valuesNamesToUpdate.push( key );
556
556
  }
557
557
 
@@ -369,7 +369,7 @@ export default class MySQLMetasParser {
369
369
  // Given that this file is updated during run time,
370
370
  // We output a typescript ambient file, so the file change doest trigger infinite app reload
371
371
  fs.outputFileSync(
372
- path.join( Container.path.server.generated, 'models.d.ts'),
372
+ path.join( Container.path.server.generated, 'models.ts'),
373
373
  types.join('\n')
374
374
  );
375
375
  }
@@ -62,7 +62,7 @@ export type TApiRegisterArgs<TRouter extends ServerRouter> = ([
62
62
 
63
63
  export type TServerController<TRouter extends ServerRouter> = (context: TRouterContext<TRouter>) => any;
64
64
 
65
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS'
65
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS'
66
66
  export type TRouteHttpMethod = HttpMethod | '*';
67
67
 
68
68
  export type TApiResponseData = {
@@ -264,6 +264,7 @@ export default class ServerRouter<
264
264
  public get = (...args: TApiRegisterArgs<this>) => this.registerApi('GET', ...args);
265
265
  public post = (...args: TApiRegisterArgs<this>) => this.registerApi('POST', ...args);
266
266
  public put = (...args: TApiRegisterArgs<this>) => this.registerApi('PUT', ...args);
267
+ public patch = (...args: TApiRegisterArgs<this>) => this.registerApi('PATCH', ...args);
267
268
  public delete = (...args: TApiRegisterArgs<this>) => this.registerApi('DELETE', ...args)
268
269
 
269
270
  protected registerApi(method: TRouteHttpMethod, ...args: TApiRegisterArgs<this>): this {
@@ -22,6 +22,9 @@ import Page from './page';
22
22
  // To move into a new npm module: json-mask
23
23
  import jsonMask from './mask';
24
24
 
25
+ // Types
26
+ import type { TBasicUser } from '@server/services/auth';
27
+
25
28
  /*----------------------------------
26
29
  - TYPES
27
30
  ----------------------------------*/
@@ -31,7 +34,7 @@ const debug = true;
31
34
  export type TBasicSSrData = {
32
35
  request: { data: TObjetDonnees, id: string },
33
36
  page: { chunkId: string, data?: TObjetDonnees },
34
- user: User | null,
37
+ user: TBasicUser | null,
35
38
  domains: TDomainsList
36
39
  }
37
40
 
@@ -45,7 +48,7 @@ export type TRouterContext<TRouter extends ServerRouter = ServerRouter> = (
45
48
  response: ServerResponse<TRouter>,
46
49
  route: TRoute,
47
50
  page?: Page,
48
- user: User,
51
+ user: TBasicUser,
49
52
 
50
53
  Router: TRouter,
51
54
  }