@communecter/cocolight-api-client 1.0.59 → 1.0.61

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@communecter/cocolight-api-client",
3
- "version": "1.0.59",
3
+ "version": "1.0.61",
4
4
  "description": "Client Axios simplifié pour l'API cocolight",
5
5
  "repository": {
6
6
  "type": "git",
@@ -4,6 +4,7 @@ import objectId from "bson-objectid";
4
4
  import * as pkg from "file-type";
5
5
 
6
6
  import { ApiAuthenticationError, ApiError, ApiResponseError, ApiValidationError } from "../error.js";
7
+ import { fromEntityJSON } from "./EntityRegistry.js";
7
8
  import { EJSON } from "../utils/compat.js";
8
9
  import { isReactive, isSignal, reactive } from "../utils/reactive.js";
9
10
 
@@ -734,6 +735,33 @@ export class BaseEntity<TServerData = any> {
734
735
  private _removeUnserializables(obj: any, seen = new WeakSet<object>()): any {
735
736
  if (obj === null || typeof obj !== "object") return obj;
736
737
 
738
+ // Check for native types BEFORE adding to WeakSet and checking for reactive proxies
739
+ // This prevents Date objects from being processed as regular objects
740
+ if (obj instanceof Date) {
741
+ return obj;
742
+ }
743
+
744
+ if (obj instanceof RegExp) {
745
+ return obj;
746
+ }
747
+
748
+ // Preserve ObjectID instances (both bson-objectid and custom ObjectID)
749
+ if (obj && typeof obj === "object" && "_bsontype" in obj && obj._bsontype === "ObjectID") {
750
+ return obj;
751
+ }
752
+
753
+ // Preserve binary types (Uint8Array, Buffer, etc.)
754
+ if (obj instanceof Uint8Array || ArrayBuffer.isView(obj)) {
755
+ return obj;
756
+ }
757
+
758
+ // If the object is a BaseEntity instance, serialize it via toJSON()
759
+ // This ensures nested entities (like author, target in News) are properly serialized
760
+ if (obj instanceof BaseEntity) {
761
+ return obj.toJSON();
762
+ }
763
+
764
+ // Now check for circular references
737
765
  if (seen.has(obj)) return null;
738
766
  seen.add(obj);
739
767
 
@@ -771,12 +799,57 @@ export class BaseEntity<TServerData = any> {
771
799
 
772
800
  /**
773
801
  * Restaure les données sérialisées en un objet d'origine.
802
+ * Désérialise récursivement les entités imbriquées qui ont le marqueur __isSerializedEntity.
774
803
  *
775
804
  * @param obj - L'objet à restaurer.
805
+ * @param parent - Instance parente optionnelle pour désérialiser les entités imbriquées.
776
806
  * @returns L'objet restauré.
777
807
  */
778
- static _revive(obj: object): any {
779
- return EJSON.fromJSONValue(obj);
808
+ static _revive(obj: object, parent?: ApiClient | BaseEntity<any> | null): any {
809
+ // D'abord, restaurer les dates EJSON
810
+ const revived = EJSON.fromJSONValue(obj);
811
+
812
+ // Ensuite, parcourir récursivement pour désérialiser les entités imbriquées
813
+ return this._deserializeNestedEntities(revived, parent);
814
+ }
815
+
816
+ /**
817
+ * Parcourt récursivement un objet et désérialise les entités imbriquées.
818
+ *
819
+ * @param obj - L'objet à parcourir.
820
+ * @param parent - Instance parente pour les entités.
821
+ * @returns L'objet avec les entités désérialisées.
822
+ * @private
823
+ */
824
+ private static _deserializeNestedEntities(obj: any, parent?: ApiClient | BaseEntity<any> | null): any {
825
+ if (obj === null || typeof obj !== "object") {
826
+ return obj;
827
+ }
828
+
829
+ // Si c'est un objet Date, RegExp, ou autre type natif, le retourner tel quel
830
+ if (obj instanceof Date || obj instanceof RegExp) {
831
+ return obj;
832
+ }
833
+
834
+ // Si c'est un array, parcourir chaque élément
835
+ if (Array.isArray(obj)) {
836
+ return obj.map(item => this._deserializeNestedEntities(item, parent));
837
+ }
838
+
839
+ // Si c'est une entité sérialisée, la désérialiser
840
+ // On vérifie les marqueurs d'une entité sérialisée
841
+ if (obj.__isSerializedEntity && obj.__entityTag && obj.serverData) {
842
+ // Désérialiser l'entité imbriquée via EntityRegistry
843
+ return fromEntityJSON(obj, parent);
844
+ }
845
+
846
+ // Sinon, parcourir les propriétés de l'objet et désérialiser récursivement
847
+ const result: any = {};
848
+ for (const [key, value] of Object.entries(obj)) {
849
+ result[key] = this._deserializeNestedEntities(value, parent);
850
+ }
851
+
852
+ return result;
780
853
  }
781
854
 
782
855
  /**
@@ -797,7 +870,7 @@ export class BaseEntity<TServerData = any> {
797
870
  }
798
871
  const { serverData } = json as { serverData: object };
799
872
 
800
- const instance = this.fromServerData(this._revive(serverData), parent as ApiClient | ParentLike, deps || {});
873
+ const instance = this.fromServerData(this._revive(serverData, parent), parent as ApiClient | ParentLike, deps || {});
801
874
 
802
875
  return instance;
803
876
  }
@@ -57,10 +57,18 @@ export function fromEntityJSON(json: unknown, parent: ApiClient | BaseEntity | n
57
57
  // On gère null / non-objet / pas une entité → on renvoie tel quel (ou null si tu préfères)
58
58
  if (!isEntityJSON(json)) return json;
59
59
 
60
- // Ici, TS sait que json.__entityTag existe
61
- if (!json.serverData?.collection) return json;
60
+ // Récupérer la collection depuis serverData, ou la dériver depuis __entityTag
61
+ let collection: CollectionKey | null | undefined = json.serverData?.collection;
62
62
 
63
- const meta = _getEntityMeta(json.serverData.collection, json.__entityTag);
63
+ // Si collection est absente, essayer de la dériver depuis __entityTag
64
+ if (!collection) {
65
+ collection = _getCollectionFromTag(json.__entityTag);
66
+ }
67
+
68
+ // Si on n'a toujours pas de collection, on ne peut pas désérialiser
69
+ if (!collection) return json;
70
+
71
+ const meta = _getEntityMeta(collection, json.__entityTag);
64
72
  if (!meta) return json;
65
73
 
66
74
  if (!meta.entityClass?.fromJSON) {
@@ -69,6 +77,24 @@ export function fromEntityJSON(json: unknown, parent: ApiClient | BaseEntity | n
69
77
  return meta.entityClass.fromJSON(json, parent, meta.deps);
70
78
  }
71
79
 
80
+ /**
81
+ * Mappe un EntityTag vers son CollectionKey correspondant.
82
+ */
83
+ function _getCollectionFromTag(tag: EntityTag): CollectionKey | null {
84
+ const map: Record<EntityTag, CollectionKey> = {
85
+ "User": "citoyens",
86
+ "Organization": "organizations",
87
+ "Project": "projects",
88
+ "Event": "events",
89
+ "Poi": "poi",
90
+ "News": "news",
91
+ "Badge": "badges",
92
+ "Comment": "comments",
93
+ "Answer": "answers"
94
+ };
95
+ return map[tag] || null;
96
+ }
97
+
72
98
  /**
73
99
  * Récupère la classe d'entité et ses dépendances à partir du type d'entité.
74
100
  */
@@ -7,6 +7,7 @@ export type {
7
7
  } from "../api/EntityRegistry.js";
8
8
 
9
9
  export type {
10
+ EntityTypes,
10
11
  TransformsMap,
11
12
  TransformFunction,
12
13
  } from "./entities.js";
@@ -328,11 +328,22 @@ export declare class BaseEntity<TServerData = any> {
328
328
  private _removeUnserializables;
329
329
  /**
330
330
  * Restaure les données sérialisées en un objet d'origine.
331
+ * Désérialise récursivement les entités imbriquées qui ont le marqueur __isSerializedEntity.
331
332
  *
332
333
  * @param obj - L'objet à restaurer.
334
+ * @param parent - Instance parente optionnelle pour désérialiser les entités imbriquées.
333
335
  * @returns L'objet restauré.
334
336
  */
335
- static _revive(obj: object): any;
337
+ static _revive(obj: object, parent?: ApiClient | BaseEntity<any> | null): any;
338
+ /**
339
+ * Parcourt récursivement un objet et désérialise les entités imbriquées.
340
+ *
341
+ * @param obj - L'objet à parcourir.
342
+ * @param parent - Instance parente pour les entités.
343
+ * @returns L'objet avec les entités désérialisées.
344
+ * @private
345
+ */
346
+ private static _deserializeNestedEntities;
336
347
  /**
337
348
  * Crée une instance d'entité à partir de données JSON.
338
349
  *
@@ -1,5 +1,5 @@
1
1
  export type { CollectionKey, EntityTag } from "../api/EntityRegistry.js";
2
- export type { TransformsMap, TransformFunction, } from "./entities.js";
2
+ export type { EntityTypes, TransformsMap, TransformFunction, } from "./entities.js";
3
3
  export type { SocialNetworkPayload, } from "./payloads.js";
4
4
  export type { UserTransforms, OrganizationTransforms, ProjectTransforms, EventTransforms } from "./transforms.js";
5
5
  export type { BaseApiResponse, ApiDataResponse, ApiErrorResponse, PaginatedApiResponse, GetElementsKeyResponse, ApiResponse } from "./api-responses.js";