@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/dist/cocolight-api-client.browser.js +1 -1
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js.map +1 -1
- package/package.json +1 -1
- package/src/api/BaseEntity.ts +76 -3
- package/src/api/EntityRegistry.ts +29 -3
- package/src/types/index.ts +1 -0
- package/types/api/BaseEntity.d.ts +12 -1
- package/types/types/index.d.ts +1 -1
package/package.json
CHANGED
package/src/api/BaseEntity.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
//
|
|
61
|
-
|
|
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
|
-
|
|
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
|
*/
|
package/src/types/index.ts
CHANGED
|
@@ -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
|
*
|
package/types/types/index.d.ts
CHANGED
|
@@ -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";
|