@communecter/cocolight-api-client 1.0.31 → 1.0.33

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.
@@ -0,0 +1,66 @@
1
+ export const EntityRegistry = new Map();
2
+
3
+ /**
4
+ * Enregistre une entité dans la registry.
5
+ * @param {string} tag - ex: "User", "Organization"
6
+ * @param {Function} EntityClass - la classe constructeur
7
+ */
8
+ export function registerEntity(tag, EntityClass) {
9
+ EntityRegistry.set(tag, EntityClass);
10
+ }
11
+
12
+ /**
13
+ * Récupère une instance depuis un JSON générique.
14
+ * @param {Object} json - doit contenir __entityTag
15
+ * @param {Object} parent - ApiClient ou entité parent
16
+ * @param {Object} deps - dépendances (comme dans le constructeur)
17
+ * @returns {BaseEntity|null}
18
+ */
19
+ export function fromEntityJSON(json, parent = null) {
20
+ if (!json?.__entityTag) return null;
21
+ if (!json._serverData?.collection) return json;
22
+ const meta = _getEntityMeta(json._serverData.collection, json.__entityTag);
23
+ if (!meta) return json;
24
+ if (!meta?.entityClass?.fromJSON) throw new Error(`Classe inconnue ou fromJSON manquant pour ${json.__entityTag}`);
25
+ return meta.entityClass.fromJSON(json, parent, meta.deps);
26
+ }
27
+
28
+ /**
29
+ * Récupère la classe d'entité et ses dépendances à partir du type d'entité.
30
+ *
31
+ * @param {string} entityType - Le type d'entité.
32
+ * @param {string} __entityTag - Le tag de l'entité.
33
+ * @returns {Object|null} - Un objet contenant la classe d'entité et ses dépendances, ou null si le type d'entité n'est pas trouvé.
34
+ */
35
+ function _getEntityMeta(entityType, __entityTag) {
36
+ const selfClass = EntityRegistry.get(__entityTag);
37
+ const selfTag = __entityTag;
38
+
39
+ const commonDeps = {
40
+ EndpointApi: EntityRegistry.get("EndpointApi"),
41
+ User: selfTag === "User" ? selfClass : EntityRegistry.get("User"),
42
+ Organization: selfTag === "Organization" ? selfClass : EntityRegistry.get("Organization"),
43
+ Project: selfTag === "Project" ? selfClass : EntityRegistry.get("Project"),
44
+ Event: selfTag === "Event" ? selfClass : EntityRegistry.get("Event"),
45
+ Poi: selfTag === "Poi" ? selfClass : EntityRegistry.get("Poi"),
46
+ Badge: selfTag === "Badge" ? selfClass : EntityRegistry.get("Badge"),
47
+ News: selfTag === "News" ? selfClass : EntityRegistry.get("News")
48
+ };
49
+
50
+ const map = {
51
+ citoyens: { entityClass: commonDeps.User, deps: commonDeps },
52
+ organizations:{ entityClass: commonDeps.Organization, deps: commonDeps },
53
+ projects: { entityClass: commonDeps.Project, deps: commonDeps },
54
+ events: { entityClass: commonDeps.Event, deps: { ...commonDeps, Badge: undefined } },
55
+ poi: { entityClass: commonDeps.Poi, deps: { ...commonDeps, Badge: undefined, News: undefined } },
56
+ news: { entityClass: commonDeps.News, deps: { ...commonDeps } },
57
+ badges: { entityClass: commonDeps.Badge, deps: {
58
+ EndpointApi: commonDeps.EndpointApi,
59
+ User: commonDeps.User,
60
+ Organization: commonDeps.Organization,
61
+ Project: commonDeps.Project
62
+ } }
63
+ };
64
+
65
+ return map[entityType] || null;
66
+ }
@@ -180,32 +180,38 @@ export class Organization extends BaseEntity {
180
180
  *
181
181
  *
182
182
  */
183
- async getMembers(data = {}, options = {}, isNext = false) {
183
+ async getMembers(data = {}, options = {}) {
184
184
  data.searchType = this._getDefaultFromEndpoint("GET_MEMBERS_ADMIN", "searchType");
185
185
  // data.searchBy = "ALL";
186
- return this._paginateWith(data, isNext, async (finalData) => {
187
-
188
- const { toBeValidated, isAdmin, isAdminPending, isInviting, roles = [] } = options;
189
-
190
- if(this.isMe){
191
- finalData.pathParams = { type: this.getEntityType(), id: this.id };
192
- // finalData.filters = {
193
- // [`links.memberOf.${this.id}`]: { "$exists": true },
194
- // [`links.memberOf.${this.id}.toBeValidated`]: { "$exists": false },
195
- // [`links.memberOf.${this.id}.isInviting`]: { "$exists": false }
196
- // };
197
- finalData.filters = this._buildLinkFilters(this.id, { linkType: "memberOf", toBeValidated, isAdmin, isAdminPending, isInviting, roles });
198
- } else {
199
- delete finalData?.pathParams;
200
- finalData.filters = this._buildLinkFilters(this.id, { linkType: "memberOf", toBeValidated: false, isAdmin, isInviting, roles });
201
- }
186
+
187
+ const paginator = this._createPaginatorEngine({
188
+ initialData: data,
189
+ finalizer: async (finalData) => {
190
+
191
+ const { toBeValidated, isAdmin, isAdminPending, isInviting, roles = [] } = options;
192
+
193
+ if(this.isMe){
194
+ finalData.pathParams = { type: this.getEntityType(), id: this.id };
195
+ // finalData.filters = {
196
+ // [`links.memberOf.${this.id}`]: { "$exists": true },
197
+ // [`links.memberOf.${this.id}.toBeValidated`]: { "$exists": false },
198
+ // [`links.memberOf.${this.id}.isInviting`]: { "$exists": false }
199
+ // };
200
+ finalData.filters = this._buildLinkFilters(this.id, { linkType: "memberOf", toBeValidated, isAdmin, isAdminPending, isInviting, roles });
201
+ } else {
202
+ delete finalData?.pathParams;
203
+ finalData.filters = this._buildLinkFilters(this.id, { linkType: "memberOf", toBeValidated: false, isAdmin, isInviting, roles });
204
+ }
202
205
 
203
- const fetchFn = this.isMe
204
- ? () => this.callIsMe(() => this.endpointApi.getMembersAdmin(finalData))
205
- : () => this.endpointApi.getMembersNoAdmin(finalData);
206
+ const fetchFn = this.isMe
207
+ ? () => this.callIsMe(() => this.endpointApi.getMembersAdmin(finalData))
208
+ : () => this.endpointApi.getMembersNoAdmin(finalData);
206
209
 
207
- return fetchFn();
210
+ return fetchFn();
211
+ }
208
212
  });
213
+
214
+ return paginator.next();
209
215
  }
210
216
 
211
217
  /**
@@ -372,8 +378,8 @@ export class Organization extends BaseEntity {
372
378
  * @returns {Promise<Object>} - Résultat de la recherche.
373
379
  * @throws {ApiError} - Si le slug ou l'id de l'organisation n'est pas défini.
374
380
  */
375
- async searchCostum(data = {}, isNext = false) {
376
- return super.searchCostum(data, isNext);
381
+ async searchCostum(data = {}) {
382
+ return super.searchCostum(data);
377
383
  }
378
384
 
379
385
  }
@@ -190,33 +190,39 @@ export class Project extends BaseEntity {
190
190
  * const invitingContributors = await project.getContributors({}, { isInviting: true });
191
191
  *
192
192
  */
193
- async getContributors(data = {}, options = {}, isNext = false) {
193
+ async getContributors(data = {}, options = {}) {
194
194
  data.searchType = this._getDefaultFromEndpoint("GET_CONTRIBUTORS_ADMIN", "searchType");
195
195
  // data.searchBy = "ALL";
196
- return this._paginateWith(data, isNext, async (finalData) => {
197
-
198
- const { toBeValidated, isAdmin, isInviting, isAdminPending, roles = [] } = options;
199
-
200
- if(this.isMe){
201
- finalData.pathParams = { type: this.getEntityType(), id: this.id };
202
- // NOTE : dans le schema je crois que si pas de finalData.filters alors le default ce fait avec finalData.pathParams
203
- // finalData.filters = {
204
- // [`links.projects.${this.id}`]: { "$exists": true },
205
- // [`links.projects.${this.id}.toBeValidated`]: { "$exists": false },
206
- // [`links.projects.${this.id}.isInviting`]: { "$exists": false }
207
- // };
208
- finalData.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated, isAdmin, isAdminPending, isInviting, roles });
209
- } else {
210
- delete finalData?.pathParams;
211
- finalData.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated: false, isAdmin, isInviting, roles });
212
- }
196
+
197
+ const paginator = this._createPaginatorEngine({
198
+ initialData: data,
199
+ finalizer: async (finalData) => {
200
+
201
+ const { toBeValidated, isAdmin, isInviting, isAdminPending, roles = [] } = options;
202
+
203
+ if(this.isMe){
204
+ finalData.pathParams = { type: this.getEntityType(), id: this.id };
205
+ // NOTE : dans le schema je crois que si pas de finalData.filters alors le default ce fait avec finalData.pathParams
206
+ // finalData.filters = {
207
+ // [`links.projects.${this.id}`]: { "$exists": true },
208
+ // [`links.projects.${this.id}.toBeValidated`]: { "$exists": false },
209
+ // [`links.projects.${this.id}.isInviting`]: { "$exists": false }
210
+ // };
211
+ finalData.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated, isAdmin, isAdminPending, isInviting, roles });
212
+ } else {
213
+ delete finalData?.pathParams;
214
+ finalData.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated: false, isAdmin, isInviting, roles });
215
+ }
213
216
 
214
- const fetchFn = this.isMe
215
- ? () => this.callIsMe(() => this.endpointApi.getContributorsAdmin(finalData))
216
- : () => this.endpointApi.getContributorsNoAdmin(finalData);
217
+ const fetchFn = this.isMe
218
+ ? () => this.callIsMe(() => this.endpointApi.getContributorsAdmin(finalData))
219
+ : () => this.endpointApi.getContributorsNoAdmin(finalData);
217
220
 
218
- return fetchFn();
221
+ return fetchFn();
222
+ }
219
223
  });
224
+
225
+ return paginator.next();
220
226
  }
221
227
 
222
228
  /**
package/src/api/User.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ApiError, ApiResponseError } from "../error.js";
1
+ import { ApiError } from "../error.js";
2
2
  import BaseEntity from "./BaseEntity.js";
3
3
  import { UserMixin } from "../mixin/UserMixin.js";
4
4
 
@@ -284,26 +284,32 @@ export class User extends BaseEntity {
284
284
  * Récupérer les organisations d'un utilisateur : Récupère la liste des organisations auxquelles l'utilisateur appartient.
285
285
  * Constant : GET_ORGANIZATIONS_ADMIN | GET_ORGANIZATIONS_NO_ADMIN
286
286
  */
287
- async getOrganizations(data = {}, isNext = false) {
287
+ async getOrganizations(data = {}) {
288
288
  data.searchType = this._getDefaultFromEndpoint("GET_ORGANIZATIONS_NO_ADMIN", "searchType");
289
289
  // data.searchBy = "ALL";
290
- return this._paginateWith(data, isNext, async (finalData) => {
291
- delete finalData?.pathParams;
292
290
 
293
- const fetchFn = this.isMe
294
- ? () => this.callIsMe(() => this.endpointApi.getOrganizationsAdmin(finalData))
295
- : () => this.endpointApi.getOrganizationsNoAdmin(finalData);
291
+ const paginator = this._createPaginatorEngine({
292
+ initialData: data,
293
+ finalizer: async (finalData) => {
294
+ delete finalData?.pathParams;
295
+
296
+ const fetchFn = this.isMe
297
+ ? () => this.callIsMe(() => this.endpointApi.getOrganizationsAdmin(finalData))
298
+ : () => this.endpointApi.getOrganizationsNoAdmin(finalData);
296
299
 
297
- if (!this.isMe && !finalData.filters) {
298
- finalData.filters = {
299
- [`links.members.${this.id}`]: { "$exists": true },
300
- [`links.members.${this.id}.toBeValidated`]: { "$exists": false },
301
- [`links.members.${this.id}.isInviting`]: { "$exists": false }
302
- };
300
+ if (!this.isMe && !finalData.filters) {
301
+ finalData.filters = {
302
+ [`links.members.${this.id}`]: { "$exists": true },
303
+ [`links.members.${this.id}.toBeValidated`]: { "$exists": false },
304
+ [`links.members.${this.id}.isInviting`]: { "$exists": false }
305
+ };
306
+ }
307
+
308
+ return fetchFn();
303
309
  }
304
-
305
- return fetchFn();
306
310
  });
311
+
312
+ return paginator.next();
307
313
  }
308
314
 
309
315
  /**
@@ -337,50 +343,56 @@ export class User extends BaseEntity {
337
343
  * actuellement, c'est tous les utilisateurs connectés
338
344
  */
339
345
  async getFriends(data = {}) {
340
- delete data?.pathParams;
341
-
342
- if (!this.isMe){
343
- // is not me add id
344
- data.pathParams = { id: this.id };
345
- }
346
+ data.searchType = this._getDefaultFromEndpoint("GET_FRIENDS_ADMIN", "searchType");
347
+ // data.searchBy = "ALL";
346
348
 
347
- const arrayObjet = await this.endpointApi.getFriendsAdmin(data);
348
- if (!Array.isArray(arrayObjet.results)){
349
- throw new ApiResponseError("Erreur lors de la récupération des amis administrables.", 500, arrayObjet);
349
+ const paginator = this._createPaginatorEngine({
350
+ initialData: data,
351
+ finalizer: async (finalData) => {
350
352
 
351
- }
353
+ delete finalData?.pathParams;
354
+
355
+ if (!this.isMe){
356
+ // is not me add id
357
+ finalData.pathParams = { id: this.id };
358
+ }
352
359
 
353
- const rawList = this._linkEntities(arrayObjet.results);
360
+ return this.endpointApi.getFriendsAdmin(finalData);;
361
+ }
362
+ });
354
363
 
355
- return {
356
- count: arrayObjet?.count?.citoyens ?? 0,
357
- results: rawList
358
- };
364
+ return paginator.next();
359
365
  }
360
366
 
361
367
  /**
362
368
  * Récupérer les suivis
363
369
  * Constant : GET_SUBSCRIPTIONS / GET_SUBSCRIPTIONS_ADMIN
364
370
  */
365
- async getSubscriptions(data = {}, isNext = false) {
371
+ async getSubscriptions(data = {}) {
366
372
  data.searchType = this._getDefaultFromEndpoint("GET_SUBSCRIPTIONS", "searchType");
367
373
  // data.searchBy = "ALL";
368
- return this._paginateWith(data, isNext, async (finalData) => {
369
374
 
370
- delete finalData?.pathParams;
375
+ const paginator = this._createPaginatorEngine({
376
+ initialData: data,
377
+ finalizer: async (finalData) => {
378
+
379
+ delete finalData?.pathParams;
371
380
 
372
- const fetchFn = this.isMe
373
- ? () => this.callIsMe(() => this.endpointApi.getSubscriptionsAdmin(finalData))
374
- : () => this.endpointApi.getSubscriptions(finalData);
381
+ const fetchFn = this.isMe
382
+ ? () => this.callIsMe(() => this.endpointApi.getSubscriptionsAdmin(finalData))
383
+ : () => this.endpointApi.getSubscriptions(finalData);
375
384
 
376
- if (!this.isMe && !finalData.filters) {
377
- finalData.filters = {
378
- [`links.followers.${this.id}`]: { "$exists": true },
379
- };
380
- }
385
+ if (!this.isMe && !finalData.filters) {
386
+ finalData.filters = {
387
+ [`links.followers.${this.id}`]: { "$exists": true },
388
+ };
389
+ }
381
390
 
382
- return fetchFn();
391
+ return fetchFn();
392
+ }
383
393
  });
394
+
395
+ return paginator.next();
384
396
  }
385
397
 
386
398
  /**
package/src/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { fromEntityJSON } from "./api/EntityRegistry.js";
1
2
  import Api from "./Api.js";
2
3
  import ApiClient from "./ApiClient.js";
3
4
  import * as error from "./error.js";
@@ -25,6 +26,9 @@ export default {
25
26
  createDefaultMultiServerTokenStorageStrategy,
26
27
  MultiServerTokenStorageStrategy
27
28
  },
29
+ helper: {
30
+ fromEntityJSON
31
+ },
28
32
 
29
33
  OfflineClientManager
30
34
  };