@communecter/cocolight-api-client 1.0.8 → 1.0.10

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/src/api/User.js CHANGED
@@ -1,66 +1,128 @@
1
- import { ApiResponseError } from "../error.js";
2
- import { EntityMixin } from "./EntityMixin.js";
3
- import { NewsMixin } from "./NewsMixin.js";
4
- import { UserMixin } from "./UserMixin.js";
5
- import { UtilMixin } from "./UtilMixin.js";
1
+ import { ApiError, ApiResponseError } from "../error.js";
2
+ import { DraftStateMixin } from "../mixin/DraftStateMixin.js";
3
+ import { MutualEntityMixin } from "../mixin/MutualEntityMixin.js";
4
+ import { UserMixin } from "../mixin/UserMixin.js";
5
+ import { UtilMixin } from "../mixin/UtilMixin.js";
6
6
 
7
7
  // User.js
8
8
  export class User {
9
- // Champs privés pour protéger l'état
10
- #id;
11
- #slug;
12
- #data;
9
+ #draftData = {};
10
+ #initialDraftData = {};
11
+ #serverData = null;
12
+
13
+ static entityType = "citoyens";
14
+
15
+ static SCHEMA_CONSTANTS = [
16
+ "UPDATE_BLOCK_DESCRIPTION",
17
+ "UPDATE_BLOCK_INFO",
18
+ "UPDATE_BLOCK_SOCIAL",
19
+ "UPDATE_BLOCK_LOCALITY",
20
+ "UPDATE_BLOCK_SLUG",
21
+ "PROFIL_IMAGE"
22
+ ];
23
+
24
+ static UPDATE_BLOCKS = new Map([
25
+ ["UPDATE_BLOCK_DESCRIPTION", "updateDescription"],
26
+ ["UPDATE_BLOCK_SOCIAL", "updateSocial"],
27
+ ["UPDATE_BLOCK_LOCALITY", "updateLocality"],
28
+ ["UPDATE_BLOCK_INFO", "updateInfo"],
29
+ ["UPDATE_BLOCK_SLUG", "updateSlug"],
30
+ ["PROFIL_IMAGE", "updateImageProfil"]
31
+ ]);
13
32
 
14
33
  /**
15
34
  * Crée une instance de User.
16
- * @param {ApiClient} apiClient - L'instance d'ApiClient.
17
- * @param {Object} identifier - Objet contenant { id } ou { slug }.
18
- * @param {Object} [data={}] - Données supplémentaires.
35
+ *
36
+ * @param {ApiClient} apiClient - Le client API connecté.
37
+ * @param {Object} data - Données initiales (peuvent inclure `id`, `slug`, etc.).
38
+ * @param {string} [data.id] - ID de l'utilisateur.
39
+ * @param {string} [data.slug] - Slug de l'utilisateur.
40
+ * @param {Object} deps - Dépendances injectées.
41
+ * @param {function|object} deps.EndpointApi - Classe ou instance de EndpointApi.
42
+ * @param {function} deps.Organization - Classe Organization.
43
+ * @param {function} deps.Project - Classe Project.
44
+ * @param {function} deps.News - Classe News.
45
+ *
46
+ * @throws {ApiError} - Si des dépendances nécessaires sont manquantes ou invalides.
19
47
  */
20
48
 
21
- constructor(apiClient, { id, slug } = {}, data = {}) {
22
- if (!id && !slug) {
23
- throw new Error("Vous devez fournir un id ou un slug pour créer un User.");
49
+ constructor(apiClient, data = {}, deps = {}) {
50
+ this.__entityTag = "User";
51
+
52
+ if(!deps.EndpointApi){
53
+ throw new ApiError("EndpointApi class must be injected to avoid circular dependency.");
24
54
  }
55
+ if (!data?.id && !data?.slug) {
56
+ throw new ApiError("Vous devez fournir un id ou un slug pour créer un User.");
57
+ }
58
+
59
+ if (!deps.Organization) throw new ApiError("Organization class must be injected.");
60
+ if (!deps.Project) throw new ApiError("Project class must be injected.");
61
+ if (!deps.News) throw new ApiError("News class must be injected.");
62
+
25
63
  this.apiClient = apiClient;
26
- this.#id = id || null;
27
- this.#slug = slug || null;
28
- this.#data = data;
64
+
65
+ this.deps = deps;
66
+
67
+ // Gérer les deux cas : fonction constructeur ou instance
68
+ if (typeof deps.EndpointApi === "function") {
69
+ this.endpointApi = new deps.EndpointApi(this.apiClient);
70
+ } else if (typeof deps.EndpointApi === "object") {
71
+ this.endpointApi = deps.EndpointApi;
72
+ } else {
73
+ throw new ApiError("deps.EndpointApi doit être une classe ou une instance valide.");
74
+ }
75
+
76
+ this.#serverData = null;
77
+
78
+ const { draft, proxy } = this.buildDraftAndProxy({
79
+ data: { ...data, ...this.defaultFields },
80
+ serverData: this.#serverData,
81
+ constant: User.SCHEMA_CONSTANTS,
82
+ apiClient: this.apiClient,
83
+ transforms: this.transforms,
84
+ removeFields: this.removeFields
85
+ });
86
+
87
+ this.#initialDraftData = JSON.parse(JSON.stringify(draft)); // snapshot propre
88
+ this.#draftData = draft;
89
+ this.data = proxy;
29
90
  }
30
-
31
- // Getters en lecture seule pour chaque propriété
91
+
32
92
  get id() {
33
- return this.#id;
93
+ return this.#draftData.id || null;
34
94
  }
35
95
 
36
96
  _id(newId) {
37
- this.#id = newId;
97
+ this.#draftData.id = newId;
38
98
  }
39
-
99
+
40
100
  get slug() {
41
- return this.#slug;
42
- }
43
-
44
- _slug(newSlug) {
45
- this.#slug = newSlug;
101
+ return this.#draftData.slug || null;
46
102
  }
47
103
 
48
104
  get isConnected() {
49
105
  return this.apiClient.isConnected;
50
106
  }
51
107
 
52
- // Getter pour accéder aux données
53
- get data() {
54
- return this.#data;
55
- }
56
-
57
- // Méthode interne qui permet de mettre à jour les données
58
108
  _setData(newData) {
59
- this.#data = newData;
109
+ this.#serverData = { ...newData };
110
+
111
+ const { draft, proxy } = this.buildDraftAndProxy({
112
+ data: { ...newData, ...this.defaultFields },
113
+ serverData: this.#serverData,
114
+ constant: User.SCHEMA_CONSTANTS,
115
+ apiClient: this.apiClient,
116
+ transforms: this.transforms,
117
+ removeFields: this.removeFields
118
+ });
119
+ this.#initialDraftData = JSON.parse(JSON.stringify(draft));
120
+ this.#draftData = draft;
121
+ this.data = proxy;
60
122
  }
61
123
 
62
124
  getEntityType() {
63
- return "citoyens";
125
+ return User.entityType;
64
126
  }
65
127
 
66
128
  get userId() {
@@ -71,6 +133,23 @@ export class User {
71
133
  return this.isConnected && this.userId === this.id;
72
134
  }
73
135
 
136
+ get draftData() {
137
+ return this.#draftData;
138
+ }
139
+
140
+ get initialDraftData() {
141
+ return this.#initialDraftData;
142
+ }
143
+
144
+ get serverData() {
145
+ return this.#serverData;
146
+ }
147
+
148
+ async refresh() {
149
+ if (!this.id) throw new ApiError("Impossible de rafraîchir sans ID.");
150
+ return this.get();
151
+ }
152
+
74
153
  /**
75
154
  * Récupère le profil complet de l'utilisateur.
76
155
  * Si l'utilisateur est connecté, on appelle le endpoint ME_INFO_URL,
@@ -78,13 +157,15 @@ export class User {
78
157
  *
79
158
  * @returns {Promise<Object>} Le profil complet.
80
159
  */
81
- async getProfil() {
160
+ async get() {
82
161
  return this.apiClient.safeCall(async () => {
83
162
  if (this.isMe) {
84
- const data = await this._meInfoUrl();
163
+ const data = await this.endpointApi.meInfoUrl();
164
+ this._setData(data);
85
165
  return data;
86
166
  } else {
87
167
  const data = await this.getPublicProfile();
168
+ this._setData(data);
88
169
  return data;
89
170
  }
90
171
  });
@@ -95,7 +176,7 @@ export class User {
95
176
  * Constant : CHANGE_PASSWORD
96
177
  */
97
178
  async changePassword(data = {}) {
98
- return this.callIsMe(() => this._changePassword(data));
179
+ return this.callIsMe(() => this.endpointApi.changePassword(data));
99
180
  }
100
181
 
101
182
  /**
@@ -103,15 +184,77 @@ export class User {
103
184
  * Constant : DELETE_ACCOUNT
104
185
  */
105
186
  async delete(data = {}) {
106
- return this.callIsMe(() => this._deleteAccount(data));
187
+ return this.callIsMe(() => this.endpointApi.deleteAccount(data));
107
188
  }
108
189
 
190
+ /**
191
+ * Sauvegarde les modifications de l'utilisateur en appelant les endpoints correspondants.
192
+ * Seul l'utilisateur connecté peut se modifier lui-même.
193
+ *
194
+ * @returns {Promise<Object>} - Données serveur mises à jour si applicable.
195
+ * @throws {ApiError} - Si l'utilisateur n'est pas autorisé.
196
+ */
197
+ async save() {
198
+
199
+ if(!this.isMe){
200
+ throw new ApiError("Vous devez être connecté et être l'utilisateur pour sauvegarder.");
201
+ }
202
+
203
+ const payload = { ...this.#draftData };
204
+
205
+ if (this.id) {
206
+ const hasChanged = await this._update(payload);
207
+ if (hasChanged) {
208
+ // this._updateInitialDraftSnapshot();
209
+ await this.refresh();
210
+ }
211
+ return this.#serverData;
212
+ }
213
+
214
+ }
215
+
216
+ /**
217
+ * Met à jour les blocs modifiés de l'utilisateur via les constantes de schéma définies.
218
+ *
219
+ * @param {Object} payload - Données courantes à comparer et envoyer.
220
+ * @returns {Promise<boolean>} - Indique s'il y a eu une modification réelle.
221
+ */
222
+ async _update(payload){
223
+ if(payload.id){
224
+ delete payload.id;
225
+ }
226
+
227
+ let hasChanged = false;
228
+
229
+ // Sinon, on fait les updates en blocs
230
+ for (const [constant, methodName] of User.UPDATE_BLOCKS) {
231
+ const blockData = this.extractChangedFieldsFromSchema(
232
+ this.apiClient,
233
+ constant,
234
+ { ...payload, ...this.defaultFields},
235
+ () => this.initialDraftData,
236
+ this.removeFields
237
+ );
238
+ if (blockData && Object.keys(blockData).length > 0) {
239
+ await this[methodName](blockData);
240
+ hasChanged = true;
241
+ }
242
+ }
243
+
244
+ return hasChanged;
245
+ }
246
+
109
247
  /**
110
248
  * Mettre à jour les paramètres utilisateur : Mise à jour des paramètres spécifiques d'un utilisateur.
111
249
  * Constant : UPDATE_SETTINGS
250
+ * @param {Object} data - Données à mettre à jour.
251
+ * @param {"birthDate"|"email"|"locality"|"phone"|"directory"} data.type - Type de paramètre à mettre à jour.
252
+ * @param {"private"|"public"|"mask"} data.value - Nouvelle valeur du paramètre.
253
+ * @returns {Promise<void>} - Résultat de la mise à jour.
112
254
  */
113
255
  async updateSettings(data = {}) {
114
- return this.callIsMe(() => this._updateSettings(data));
256
+ await this.callIsMe(() => this.endpointApi.updateSettings(data));
257
+ await this.refresh();
115
258
  }
116
259
 
117
260
  /**
@@ -119,7 +262,7 @@ export class User {
119
262
  * Constant : UPDATE_BLOCK_DESCRIPTION
120
263
  */
121
264
  async updateDescription(data = {}) {
122
- return this.callIsMe(() => this._updateBlockDescription(data));
265
+ return this.callIsMe(() => this.endpointApi.updateBlockDescription(data));
123
266
  }
124
267
 
125
268
  /**
@@ -127,7 +270,7 @@ export class User {
127
270
  * Constant : UPDATE_BLOCK_INFO
128
271
  */
129
272
  async updateInfo(data = {}) {
130
- return this.callIsMe(() => this._updateBlockInfo(data));
273
+ return this.callIsMe(() => this.endpointApi.updateBlockInfo(data));
131
274
  }
132
275
 
133
276
  /**
@@ -135,7 +278,7 @@ export class User {
135
278
  * Constant : UPDATE_BLOCK_SOCIAL
136
279
  */
137
280
  async updateSocial(data = {}) {
138
- return this.callIsMe(() => this._updateBlockSocial(data));
281
+ return this.callIsMe(() => this.endpointApi.updateBlockSocial(data));
139
282
  }
140
283
 
141
284
  /**
@@ -143,36 +286,166 @@ export class User {
143
286
  * Constant : UPDATE_BLOCK_LOCALITY
144
287
  */
145
288
  async updateLocality(data = {}) {
146
- return this.callIsMe(() => this._updateBlockLocality(data));
289
+ return this.callIsMe(() => this.endpointApi.updateBlockLocality(data));
147
290
  }
148
291
 
149
292
  /**
150
293
  * Mettre à jour le slug d'un élément : Permet de mettre à jour le slug pour une URL simplifiée.
151
294
  * Constant : UPDATE_BLOCK_SLUG
152
295
  */
153
- async updateSlug(slug) {
296
+ async updateSlug({ slug }) {
154
297
  try {
155
- await this._check({ slug });
298
+ await this.endpointApi.check({ slug });
156
299
  } catch (error) {
157
300
  if(error instanceof ApiResponseError) {
158
301
  throw new ApiResponseError("Erreur lors de la vérification du slug.", error.status, error.data);
159
302
  }
160
303
  throw error;
161
304
  }
162
- return this.callIsMe(() => this._updateBlockSlug({ slug }));
305
+ return this.callIsMe(() => this.endpointApi.updateBlockSlug({ slug }));
163
306
  }
164
307
 
165
308
  /**
166
309
  * Mettre à jour l'image de profil : Permet de mettre à jour l'image de profil d'un utilisateur ou d'une entité.
167
310
  * Constant : PROFIL_IMAGE
168
311
  */
169
- async updateImageProfil(image) {
312
+ async updateImageProfil({ profil_avatar: image }) {
170
313
  image = await this.validateImage(image);
171
- return this.callIsMe(() => this._profilImage({ profil_avatar: image }));
314
+ return this.callIsMe(() => this.endpointApi.profilImage({ profil_avatar: image }));
315
+ }
316
+
317
+ /**
318
+ * Récupérer les organisations d'un utilisateur : Récupère la liste des organisations auxquelles l'utilisateur appartient.
319
+ * Constant : GET_ORGANIZATIONS_ADMIN | GET_ORGANIZATIONS_NO_ADMIN
320
+ */
321
+ async getOrganizations(data = {}) {
322
+ delete data?.pathParams;
323
+
324
+ const fetchFn = this.isMe
325
+ ? () => this.callIsMe(() => this.endpointApi.getOrganizationsAdmin(data))
326
+ : () => this.endpointApi.getOrganizationsNoAdmin(data);
327
+
328
+ if (!this.isMe && !data.filters) {
329
+ data.filters = {
330
+ [`links.members.${this.id}`]: { "$exists": true },
331
+ [`links.members.${this.id}.toBeValidated`]: { "$exists": false },
332
+ [`links.members.${this.id}.isInviting`]: { "$exists": false }
333
+ };
334
+ }
335
+
336
+ const arrayObjetOrganizations = await fetchFn();
337
+
338
+ if (!Array.isArray(arrayObjetOrganizations.results)) {
339
+ throw new ApiResponseError("Erreur lors de la récupération des organisations.", 500, arrayObjetOrganizations.results);
340
+ }
341
+
342
+ // nettoyage du count
343
+ delete arrayObjetOrganizations?.count?.spam;
344
+
345
+ // calcul du total
346
+ const totalCount = Object.values(arrayObjetOrganizations.count || {}).reduce((acc, val) => acc + val, 0);
347
+ arrayObjetOrganizations.count.total = totalCount;
348
+
349
+ // transformation des résultats
350
+ const rawOrganizationsList = arrayObjetOrganizations.results.map((orgData) =>
351
+ this.deps.Organization.fromServerData(orgData, this, {
352
+ User,
353
+ Project: this.deps.Project,
354
+ News: this.deps.News,
355
+ EndpointApi: this.deps.EndpointApi
356
+ })
357
+ );
358
+
359
+ return {
360
+ count: arrayObjetOrganizations.count,
361
+ results: rawOrganizationsList
362
+ };
363
+ }
364
+
365
+ /**
366
+ * Crée une instance d'organisation et récupère son profil si nécessaire.
367
+ *
368
+ * @param {Object} organizationData - Les données nécessaires pour initialiser l'organisation.
369
+ * @returns {Promise<Organization>} Une promesse qui résout l'objet Organisation créé.
370
+ * @throws {Error} Si une erreur se produit lors de la création de l'organisation.
371
+ */
372
+ async organization(organizationData = {}, ) {
373
+ try {
374
+ const organization = new this.deps.Organization(this, organizationData, { User, Project: this.deps.Project, News: this.deps.News, EndpointApi : this.deps.EndpointApi });
375
+ if (organizationData.id || organizationData.slug) {
376
+ await organization.get();
377
+ }
378
+ return organization;
379
+ } catch (error) {
380
+ this.apiClient._logger.error(`[Api.${this.__entityTag}.organization] Erreur lors de la création d'une instance organization :`, error.message);
381
+ throw error;
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Récupérer les projets d'un utilisateur : Récupère la liste des projets auxquels l'utilisateur contribue.
387
+ * Constant : GET_PROJECTS_ADMIN | GET_PROJECTS_NO_ADMIN
388
+ */
389
+ async getProjects(data = {}) {
390
+ delete data?.pathParams;
391
+
392
+ const fetchFn = this.isMe
393
+ ? () => this.callIsMe(() => this.endpointApi.getProjectsAdmin(data))
394
+ : () => this.endpointApi.getProjectsNoAdmin(data);
395
+
396
+ if (!this.isMe && !data.filters) {
397
+ data.filters = {
398
+ "$or": {
399
+ [`links.contributors.${this.id}`]: { "$exists": true },
400
+ [`parent.${this.id}`]: { "$exists": true }
401
+ },
402
+ [`links.contributors.${this.id}`]: { "$exists": true }
403
+ // TODO : revoir les filtres pour harmoniser avec orga (schema pris de cocolight)
404
+ };
405
+ }
406
+
407
+ const arrayObjetProjects = await fetchFn();
408
+
409
+ if (!Array.isArray(arrayObjetProjects.results)) {
410
+ throw new ApiResponseError("Erreur lors de la récupération des projets.", 500, arrayObjetProjects.results);
411
+ }
412
+
413
+ const rawProjectsList = arrayObjetProjects.results.map((projectData) =>
414
+ this.deps.Project.fromServerData(projectData, this, {
415
+ User,
416
+ News: this.deps.News,
417
+ EndpointApi: this.deps.EndpointApi
418
+ })
419
+ );
420
+
421
+ return {
422
+ count: arrayObjetProjects?.count?.projects ?? 0,
423
+ results: rawProjectsList
424
+ };
425
+ }
426
+
427
+ /**
428
+ * Crée une instance de projet et récupère son profil si nécessaire.
429
+ *
430
+ * @param {Object} projectData - Les données nécessaires pour initialiser le projet.
431
+ * @returns {Promise<Project>} Une promesse qui résout l'objet Projet créé.
432
+ * @throws {Error} Si une erreur se produit lors de la création du projet.
433
+ */
434
+ async project(projectData = {}, ) {
435
+ try {
436
+ const project = new this.deps.Project(this, projectData, { User, News: this.deps.News, EndpointApi : this.deps.EndpointApi });
437
+ if (projectData.id || projectData.slug) {
438
+ await project.get();
439
+ }
440
+ return project;
441
+ } catch (error) {
442
+ this.apiClient._logger.error(`[Api.${this.__entityTag}.project] Erreur lors de la création d'une instance project :`, error.message);
443
+ throw error;
444
+ }
172
445
  }
173
446
 
174
447
  /**
175
- * Récupérer les actualités : Récupère la liste d’actualités selon plusieurs critères.
448
+ * Récupérer les actualités : Récupère la liste des actualités liées à l'utilisateur.
176
449
  * Constant : GET_NEWS
177
450
  */
178
451
  async getNews(data = {}) {
@@ -183,44 +456,81 @@ export class User {
183
456
  // is not me add id
184
457
  data.pathParams = { id: this.id };
185
458
  }
186
- return this._getNews(data);
187
- }
188
-
189
- /**
190
- * Ajouter une actualité : Ajoute une nouvelle actualité.
191
- * Constant : ADD_NEWS
192
- * @param {Object} data - Les données à envoyer.
193
- * @param {string} data.text - Contenu de l’actualité
194
- * @param {string} data.scope - Portée de l'actualité (ex: public, privé...) (default: "public")
195
- * @param {boolean} data.markdownActive - Markdown activé (true/false) (default: true)
196
- * @param {string} data.type - Type de l'objet, toujours 'news'. (default: "news")
197
- * @param {boolean} data.json - Indique que la réponse est au format JSON. (default: true)
198
- * @param {array | string} data.tags - Tags : "" pour effacer tous les tags, ou tableau de mots-clés.
199
- * @param {object} data.mediaImg - Optionnel. Informations sur les images associées à la news.
200
- * @param {number} data.mediaImg.countImages - Nombre d'images.
201
- * @param {Array<string>} data.mediaImg.images - Liste des identifiants ou chemins d'images.
202
- * @param {object} data.mediaFile - Optionnel. Informations sur les fichiers associés à la news.
203
- * @param {number} data.mediaFile.countFiles - Nombre de fichiers.
204
- * @param {Array<string>} data.mediaFile.files - Liste des identifiants ou chemins de fichiers.
205
- * @param {object} data.mentions - Liste des mentions sous forme d'objet avec des clés dynamiques représentant l'indice de la mention.
206
- * @param {Object.<string, object>} data.mentions - Objet dont les clés keys matching ^[0-9]+$
207
- * @returns {Promise<Object>} - Les données de réponse.
208
- * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
209
- * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
210
- * @throws {Error} - En cas d'erreur inattendue.
211
- */
212
- async addNews(data = {}) {
213
- if (data.parentId) {
214
- delete data.parentId;
215
- }
216
- if (data.parentType) {
217
- delete data.parentType;
218
- }
219
- return this.callIsMe(() => this._addNews(data));
459
+ const arrayObjetNews = await this.endpointApi.getNews(data);
460
+ if(!Array.isArray(arrayObjetNews)){
461
+ throw new ApiResponseError("Erreur lors de la récupération des actualités.", 500, arrayObjetNews);
462
+ }
463
+ const rawNewsList = arrayObjetNews.map((newsData) =>
464
+ this.deps.News.fromServerData(newsData, this, { User, EndpointApi: this.deps.EndpointApi })
465
+ );
466
+
467
+ return this._createFilteredProxy(rawNewsList);
220
468
  }
221
-
469
+
470
+ /**
471
+ * Crée une instance de news et la récupère si nécessaire.
472
+ *
473
+ * @param {Object} newsData - Les données nécessaires pour initialiser la news.
474
+ * @returns {Promise<News>} Une promesse qui résout l'objet News créé.
475
+ * @throws {Error} Si une erreur se produit lors de la création de la news.
476
+ */
477
+ async news(newsData = {}, ) {
478
+ try {
479
+ const news = new this.deps.News(this, newsData, { User, EndpointApi : this.deps.EndpointApi });
480
+ if (newsData.id) {
481
+ await news.get();
482
+ }
483
+ return news;
484
+ } catch (error) {
485
+ this.apiClient._logger.error(`[Api.${this.__entityTag}.news] Erreur lors de la création d'une instance news :`, error.message);
486
+ throw error;
487
+ }
488
+ }
489
+
490
+ _updateInitialDraftSnapshot() {
491
+ this.#initialDraftData = JSON.parse(JSON.stringify(this.#draftData));
492
+ }
493
+
494
+ hasChanges() {
495
+ return JSON.stringify(this.#draftData) !== JSON.stringify(this.#initialDraftData);
496
+ }
497
+
498
+ /**
499
+ * Champs par défaut pour les schemas json ou l'on extrait les fields. (pour les if/else/then)
500
+ *
501
+ * @property {Object} defaultFields - Un objet contenant les propriétés par défaut pour l'entité User.
502
+ */
503
+ defaultFields = {
504
+ typeElement: this.getEntityType(),
505
+ };
506
+
507
+ /**
508
+ * Champs à supprimer de draft lors de la construction du proxy.
509
+ *
510
+ * @property {Array<string>} removeFields - Un tableau de chaînes représentant les champs à supprimer.
511
+ */
512
+ removeFields = [
513
+ "typeElement",
514
+ ];
515
+
516
+ /**
517
+ * Transformateurs appliqués lors de la lecture du draft.
518
+ *
519
+ * @type {Object<string, function>}
520
+ */
521
+ transforms = {
522
+ github: (val, full) => full?.socialNetwork?.github,
523
+ gitlab: (val, full) => full?.socialNetwork?.gitlab,
524
+ facebook: (val, full) => full?.socialNetwork?.facebook,
525
+ twitter: (val, full) => full?.socialNetwork?.twitter,
526
+ instagram: (val, full) => full?.socialNetwork?.instagram,
527
+ diaspora: (val, full) => full?.socialNetwork?.diaspora,
528
+ mastodon: (val, full) => full?.socialNetwork?.mastodon,
529
+ telegram: (val, full) => full?.socialNetwork?.telegram,
530
+ signal: (val, full) => full?.socialNetwork?.signal
531
+ };
222
532
  }
223
533
 
224
534
  // Incorporation des mixins dans User
225
- Object.assign(User.prototype, EntityMixin, UtilMixin, UserMixin, NewsMixin);
535
+ Object.assign(User.prototype, MutualEntityMixin, UtilMixin, UserMixin, DraftStateMixin);
226
536
 
@@ -1,6 +1,10 @@
1
1
  // UserApi.js
2
2
  import ApiClient from "../ApiClient.js";
3
3
  import { ApiResponseError } from "../error.js";
4
+ import EndpointApi from "./EndpointApi.js";
5
+ import { News } from "./News.js";
6
+ import { Organization } from "./Organization.js";
7
+ import { Project } from "./Project.js";
4
8
  import { User } from "./User.js";
5
9
 
6
10
  export class UserApi {
@@ -15,7 +19,7 @@ export class UserApi {
15
19
  // Appel à un endpoint d'authentification
16
20
  const response = await this.client.callEndpoint("AUTHENTICATE_URL", { email, password });
17
21
  // Création d'une instance de LoggedInUser à partir des données reçues
18
- this.loggedUser = new User(this.client, { id: response.data.user.id }, response.data.user);
22
+ this.loggedUser = new User(this.client, response.data.user, { EndpointApi, Organization, Project, News });
19
23
  return this.loggedUser;
20
24
  });
21
25
  }