@communecter/cocolight-api-client 1.0.129 → 1.0.130
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 +14 -3
- package/src/api/EntityRegistry.ts +43 -0
- package/src/index.ts +2 -1
- package/types/api/EntityRegistry.d.ts +21 -0
- package/types/index.d.ts +2 -1
package/package.json
CHANGED
package/src/api/BaseEntity.ts
CHANGED
|
@@ -4835,11 +4835,22 @@ export class BaseEntity<TServerData = any> {
|
|
|
4835
4835
|
...(result.projects && {
|
|
4836
4836
|
projects: (result.projects as FundingEnvelopeProjectItem[]).map((envelope) => {
|
|
4837
4837
|
const inner = envelope?.project as { collection?: string } | undefined;
|
|
4838
|
+
let linked: AnyEntity | object | undefined = envelope.project;
|
|
4838
4839
|
if (inner && typeof inner === "object") {
|
|
4839
|
-
|
|
4840
|
-
return { ...envelope, project: linked ?? envelope.project };
|
|
4840
|
+
linked = this._linkEntity(inner.collection ?? "projects", inner) ?? envelope.project;
|
|
4841
4841
|
}
|
|
4842
|
-
|
|
4842
|
+
|
|
4843
|
+
// Linker les actions imbriquées avec le Project linké comme parent sémantique.
|
|
4844
|
+
// (action.parent === Project → save/refresh/isContributor cohérents)
|
|
4845
|
+
const sd = (envelope as { serverData?: { actions?: unknown[] } }).serverData;
|
|
4846
|
+
if (sd?.actions && Array.isArray(sd.actions)
|
|
4847
|
+
&& linked && typeof (linked as BaseEntity)._linkEntity === "function") {
|
|
4848
|
+
sd.actions = sd.actions.map((action) =>
|
|
4849
|
+
(linked as BaseEntity)._linkEntity("actions", action as object) ?? action
|
|
4850
|
+
);
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4853
|
+
return { ...envelope, project: linked };
|
|
4843
4854
|
})
|
|
4844
4855
|
}),
|
|
4845
4856
|
...(result.userOrga && { userOrga: this._linkEntities(Object.values(result.userOrga)) ?? result.userOrga })
|
|
@@ -98,6 +98,49 @@ export function fromEntityJSON(json: unknown, parent: ApiClient | BaseEntity | n
|
|
|
98
98
|
return meta.entityClass.fromJSON(json, actualParent, meta.deps);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Walker récursif : parcourt un objet/tableau et ressuscite toutes les entités
|
|
103
|
+
* sérialisées (marqueurs `__isSerializedEntity` / `__entityTag`) rencontrées.
|
|
104
|
+
*
|
|
105
|
+
* Pensé pour les wrappers non-entité retournés par certains endpoints (ex: `fundingEnvelope`)
|
|
106
|
+
* ou pour réhydrater un état côté client après un transfert JSON (SSR, cache restore).
|
|
107
|
+
*
|
|
108
|
+
* Dates, RegExp et primitives sont préservées. Pour les entités, la chaîne de parents
|
|
109
|
+
* est reconstruite automatiquement depuis les méta embarquées par `toJSON()`.
|
|
110
|
+
*
|
|
111
|
+
* @param obj - L'objet à parcourir (wrapper, array, primitive…)
|
|
112
|
+
* @param parent - Parent racine (typiquement l'ApiClient côté client)
|
|
113
|
+
* @returns L'objet avec toutes les entités revived
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* // Côté client SSR : revive l'état dehydraté
|
|
117
|
+
* const apiClient = new ApiClient({ baseURL });
|
|
118
|
+
* const envelope = reviveEntities(window.__INIT__.envelope, apiClient);
|
|
119
|
+
* envelope.projects[0].serverData.actions[0]; // Action instance
|
|
120
|
+
*/
|
|
121
|
+
export function reviveEntities<T = unknown>(
|
|
122
|
+
obj: unknown,
|
|
123
|
+
parent: ApiClient | BaseEntity | null = null
|
|
124
|
+
): T {
|
|
125
|
+
if (obj === null || obj === undefined) return obj as T;
|
|
126
|
+
if (typeof obj !== "object") return obj as T;
|
|
127
|
+
if (obj instanceof Date || obj instanceof RegExp) return obj as T;
|
|
128
|
+
|
|
129
|
+
if (isEntityJSON(obj)) {
|
|
130
|
+
return fromEntityJSON(obj, parent) as T;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (Array.isArray(obj)) {
|
|
134
|
+
return obj.map(item => reviveEntities(item, parent)) as T;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const result: Record<string, unknown> = {};
|
|
138
|
+
for (const [key, value] of Object.entries(obj as object)) {
|
|
139
|
+
result[key] = reviveEntities(value, parent);
|
|
140
|
+
}
|
|
141
|
+
return result as T;
|
|
142
|
+
}
|
|
143
|
+
|
|
101
144
|
/**
|
|
102
145
|
* Mappe un EntityTag vers son CollectionKey correspondant.
|
|
103
146
|
*/
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseEntity } from "./api/BaseEntity.js";
|
|
2
|
-
import { fromEntityJSON } from "./api/EntityRegistry.js";
|
|
2
|
+
import { fromEntityJSON, reviveEntities } from "./api/EntityRegistry.js";
|
|
3
3
|
import Api from "./Api.js";
|
|
4
4
|
import ApiClient from "./ApiClient.js";
|
|
5
5
|
import * as error from "./error.js";
|
|
@@ -33,6 +33,7 @@ const cocolightApiClient = {
|
|
|
33
33
|
},
|
|
34
34
|
helper: {
|
|
35
35
|
fromEntityJSON,
|
|
36
|
+
reviveEntities,
|
|
36
37
|
restorePaginationFromJSON: BaseEntity.restorePaginationFromJSON
|
|
37
38
|
},
|
|
38
39
|
OfflineClientManager
|
|
@@ -17,6 +17,27 @@ export declare function registerEntity(tag: EntityTag, EntityClass: EntityClass)
|
|
|
17
17
|
* Si la collection ou la métadonnée d'entité est absente, renvoie l'objet d'origine.
|
|
18
18
|
*/
|
|
19
19
|
export declare function fromEntityJSON(json: unknown, parent?: ApiClient | BaseEntity | null): BaseEntity | unknown | null;
|
|
20
|
+
/**
|
|
21
|
+
* Walker récursif : parcourt un objet/tableau et ressuscite toutes les entités
|
|
22
|
+
* sérialisées (marqueurs `__isSerializedEntity` / `__entityTag`) rencontrées.
|
|
23
|
+
*
|
|
24
|
+
* Pensé pour les wrappers non-entité retournés par certains endpoints (ex: `fundingEnvelope`)
|
|
25
|
+
* ou pour réhydrater un état côté client après un transfert JSON (SSR, cache restore).
|
|
26
|
+
*
|
|
27
|
+
* Dates, RegExp et primitives sont préservées. Pour les entités, la chaîne de parents
|
|
28
|
+
* est reconstruite automatiquement depuis les méta embarquées par `toJSON()`.
|
|
29
|
+
*
|
|
30
|
+
* @param obj - L'objet à parcourir (wrapper, array, primitive…)
|
|
31
|
+
* @param parent - Parent racine (typiquement l'ApiClient côté client)
|
|
32
|
+
* @returns L'objet avec toutes les entités revived
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Côté client SSR : revive l'état dehydraté
|
|
36
|
+
* const apiClient = new ApiClient({ baseURL });
|
|
37
|
+
* const envelope = reviveEntities(window.__INIT__.envelope, apiClient);
|
|
38
|
+
* envelope.projects[0].serverData.actions[0]; // Action instance
|
|
39
|
+
*/
|
|
40
|
+
export declare function reviveEntities<T = unknown>(obj: unknown, parent?: ApiClient | BaseEntity | null): T;
|
|
20
41
|
/**
|
|
21
42
|
* Crée une instance d'entité basée sur le seul nom de la collection.
|
|
22
43
|
*/
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseEntity } from "./api/BaseEntity.js";
|
|
2
|
-
import { fromEntityJSON } from "./api/EntityRegistry.js";
|
|
2
|
+
import { fromEntityJSON, reviveEntities } from "./api/EntityRegistry.js";
|
|
3
3
|
import Api from "./Api.js";
|
|
4
4
|
import ApiClient from "./ApiClient.js";
|
|
5
5
|
import * as error from "./error.js";
|
|
@@ -31,6 +31,7 @@ declare const cocolightApiClient: {
|
|
|
31
31
|
};
|
|
32
32
|
helper: {
|
|
33
33
|
fromEntityJSON: typeof fromEntityJSON;
|
|
34
|
+
reviveEntities: typeof reviveEntities;
|
|
34
35
|
restorePaginationFromJSON: typeof BaseEntity.restorePaginationFromJSON;
|
|
35
36
|
};
|
|
36
37
|
OfflineClientManager: typeof OfflineClientManager;
|