@communecter/cocolight-api-client 1.0.128 → 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 +2 -2
- 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.ts +1 -1
- package/src/api/BaseEntity.ts +14 -3
- package/src/api/EndpointApi.types.ts +24 -4
- package/src/api/EntityRegistry.ts +43 -0
- package/src/api/Organization.ts +15 -4
- package/src/api/Project.ts +15 -2
- package/src/endpoints.module.ts +113 -98
- package/src/index.ts +2 -1
- package/types/api/EndpointApi.types.d.ts +24 -4
- package/types/api/EntityRegistry.d.ts +21 -0
- package/types/api/Organization.d.ts +5 -0
- package/types/api/Project.d.ts +6 -0
- package/types/endpoints.module.d.ts +4 -8
- package/types/index.d.ts +2 -1
package/package.json
CHANGED
package/src/Api.ts
CHANGED
|
@@ -167,7 +167,7 @@ export default class Api {
|
|
|
167
167
|
*/
|
|
168
168
|
async project(projectData: EntityData): Promise<Project> {
|
|
169
169
|
try {
|
|
170
|
-
const project = new Project(this._client, projectData, { EndpointApi, User, Organization, Event, Poi, Badge, News, Comment, Classified, Action });
|
|
170
|
+
const project = new Project(this._client, projectData, { EndpointApi, User, Organization, Event, Poi, Badge, News, Comment, Answer, Classified, Action });
|
|
171
171
|
if (!projectData.id && !projectData.slug) {
|
|
172
172
|
throw new Error("Vous devez fournir un id ou un slug pour créer une instance Project.");
|
|
173
173
|
}
|
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 })
|
|
@@ -1651,8 +1651,13 @@ export interface GetMembersNoAdminData {
|
|
|
1651
1651
|
name?: string;
|
|
1652
1652
|
/**
|
|
1653
1653
|
* Types d'entités à inclure dans la recherche
|
|
1654
|
+
*
|
|
1655
|
+
* @minItems 1
|
|
1654
1656
|
*/
|
|
1655
|
-
searchType:
|
|
1657
|
+
searchType: [
|
|
1658
|
+
"citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative",
|
|
1659
|
+
...("citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative")[]
|
|
1660
|
+
];
|
|
1656
1661
|
/**
|
|
1657
1662
|
* Critère de recherche (actuellement vide)
|
|
1658
1663
|
*/
|
|
@@ -1726,8 +1731,13 @@ export interface GetMembersAdminData {
|
|
|
1726
1731
|
name?: string;
|
|
1727
1732
|
/**
|
|
1728
1733
|
* Types d'entités à inclure dans la recherche
|
|
1734
|
+
*
|
|
1735
|
+
* @minItems 1
|
|
1729
1736
|
*/
|
|
1730
|
-
searchType:
|
|
1737
|
+
searchType: [
|
|
1738
|
+
"citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative",
|
|
1739
|
+
...("citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative")[]
|
|
1740
|
+
];
|
|
1731
1741
|
/**
|
|
1732
1742
|
* Critère de recherche (actuellement vide)
|
|
1733
1743
|
*/
|
|
@@ -2193,8 +2203,13 @@ export interface GetContributorsNoAdminData {
|
|
|
2193
2203
|
name?: string;
|
|
2194
2204
|
/**
|
|
2195
2205
|
* Types d'entités à inclure dans la recherche
|
|
2206
|
+
*
|
|
2207
|
+
* @minItems 1
|
|
2196
2208
|
*/
|
|
2197
|
-
searchType:
|
|
2209
|
+
searchType: [
|
|
2210
|
+
"citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative",
|
|
2211
|
+
...("citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative")[]
|
|
2212
|
+
];
|
|
2198
2213
|
/**
|
|
2199
2214
|
* Critère de recherche (actuellement vide)
|
|
2200
2215
|
*/
|
|
@@ -2268,8 +2283,13 @@ export interface GetContributorsAdminData {
|
|
|
2268
2283
|
name?: string;
|
|
2269
2284
|
/**
|
|
2270
2285
|
* Types d'entités à inclure dans la recherche
|
|
2286
|
+
*
|
|
2287
|
+
* @minItems 1
|
|
2271
2288
|
*/
|
|
2272
|
-
searchType:
|
|
2289
|
+
searchType: [
|
|
2290
|
+
"citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative",
|
|
2291
|
+
...("citoyens" | "NGO" | "LocalBusiness" | "Group" | "GovernmentOrganization" | "Cooperative")[]
|
|
2292
|
+
];
|
|
2273
2293
|
/**
|
|
2274
2294
|
* Critère de recherche (actuellement vide)
|
|
2275
2295
|
*/
|
|
@@ -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/api/Organization.ts
CHANGED
|
@@ -322,8 +322,12 @@ export class Organization extends BaseEntity<OrganizationItemNormalized> {
|
|
|
322
322
|
*
|
|
323
323
|
* // Récupérer les membres en attente de validation pour être admin
|
|
324
324
|
* const adminPendingMembers = await organization.getMembers({}, { isAdminPending: true });
|
|
325
|
-
*
|
|
326
|
-
*
|
|
325
|
+
*
|
|
326
|
+
* // Restreindre la recherche : uniquement les citoyens
|
|
327
|
+
* const onlyCitoyens = await organization.getMembers({}, { searchType: "citoyens" });
|
|
328
|
+
*
|
|
329
|
+
* // Restreindre la recherche : uniquement les organisations
|
|
330
|
+
* const onlyOrgas = await organization.getMembers({}, { searchType: "organizations" });
|
|
327
331
|
*/
|
|
328
332
|
async getMembers(
|
|
329
333
|
data: Partial<GetMembersAdminData | GetMembersNoAdminData> = {},
|
|
@@ -333,6 +337,7 @@ export class Organization extends BaseEntity<OrganizationItemNormalized> {
|
|
|
333
337
|
isAdminPending?: boolean;
|
|
334
338
|
isInviting?: boolean;
|
|
335
339
|
roles?: any[];
|
|
340
|
+
searchType?: "all" | "citoyens" | "organizations";
|
|
336
341
|
restoredState?: PaginatorState;
|
|
337
342
|
} = {}
|
|
338
343
|
): Promise<PaginatorPage<User | Organization>> {
|
|
@@ -344,8 +349,14 @@ export class Organization extends BaseEntity<OrganizationItemNormalized> {
|
|
|
344
349
|
/** « Snapshot » local, typé string */
|
|
345
350
|
const orgId = this.id as string;
|
|
346
351
|
|
|
347
|
-
|
|
348
|
-
|
|
352
|
+
const allTypes = this._getDefaultFromEndpoint("GET_MEMBERS_ADMIN", "searchType") as GetMembersAdminData["searchType"];
|
|
353
|
+
if (options.searchType === "citoyens") {
|
|
354
|
+
data.searchType = ["citoyens"];
|
|
355
|
+
} else if (options.searchType === "organizations") {
|
|
356
|
+
data.searchType = allTypes.filter(t => t !== "citoyens") as GetMembersAdminData["searchType"];
|
|
357
|
+
} else {
|
|
358
|
+
data.searchType = allTypes;
|
|
359
|
+
}
|
|
349
360
|
|
|
350
361
|
const paginator = this._createPaginatorEngine({
|
|
351
362
|
initialData: data,
|
package/src/api/Project.ts
CHANGED
|
@@ -232,6 +232,11 @@ export class Project extends BaseEntity<ProjectItemNormalized> {
|
|
|
232
232
|
* // Récupérer les contributeurs en attente d'invitation
|
|
233
233
|
* const invitingContributors = await project.getContributors({}, { isInviting: true });
|
|
234
234
|
*
|
|
235
|
+
* // Restreindre la recherche : uniquement les citoyens
|
|
236
|
+
* const onlyCitoyens = await project.getContributors({}, { searchType: "citoyens" });
|
|
237
|
+
*
|
|
238
|
+
* // Restreindre la recherche : uniquement les organisations
|
|
239
|
+
* const onlyOrgas = await project.getContributors({}, { searchType: "organizations" });
|
|
235
240
|
*/
|
|
236
241
|
async getContributors(
|
|
237
242
|
data: Partial<GetContributorsAdminData | GetContributorsNoAdminData> = {},
|
|
@@ -241,11 +246,19 @@ export class Project extends BaseEntity<ProjectItemNormalized> {
|
|
|
241
246
|
isAdminPending?: boolean;
|
|
242
247
|
isInviting?: boolean;
|
|
243
248
|
roles?: any[];
|
|
249
|
+
searchType?: "all" | "citoyens" | "organizations";
|
|
244
250
|
restoredState?: PaginatorState;
|
|
245
251
|
} = {}
|
|
246
252
|
): Promise<PaginatorPage<User | Organization>> {
|
|
247
|
-
|
|
248
|
-
|
|
253
|
+
const allTypes = this._getDefaultFromEndpoint("GET_CONTRIBUTORS_ADMIN", "searchType") as GetContributorsAdminData["searchType"];
|
|
254
|
+
if (options.searchType === "citoyens") {
|
|
255
|
+
data.searchType = ["citoyens"];
|
|
256
|
+
} else if (options.searchType === "organizations") {
|
|
257
|
+
data.searchType = allTypes.filter(t => t !== "citoyens") as GetContributorsAdminData["searchType"];
|
|
258
|
+
} else {
|
|
259
|
+
// "all" ou omis : on initialise explicitement (le paginator exige searchType avant la validation AJV)
|
|
260
|
+
data.searchType = allTypes;
|
|
261
|
+
}
|
|
249
262
|
|
|
250
263
|
const paginator = this._createPaginatorEngine({
|
|
251
264
|
initialData: data,
|