@communecter/cocolight-api-client 1.0.20 → 1.0.21
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/package.json +2 -1
- package/src/api/BaseEntity.js +1412 -35
- package/src/api/EndpointApi.js +443 -924
- package/src/api/EndpointApi.types.d.ts +3463 -0
- package/src/api/Organization.js +77 -0
- package/src/api/User.js +22 -45
- package/src/mixin/DraftStateMixin.js +0 -176
- package/src/mixin/EntityMixin.js +0 -428
- package/src/mixin/MutualEntityMixin.js +0 -269
- package/src/mixin/UtilMixin.js +0 -300
package/src/api/Organization.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ApiResponseError } from "../error.js";
|
|
1
2
|
import BaseEntity from "./BaseEntity.js";
|
|
2
3
|
|
|
3
4
|
export class Organization extends BaseEntity {
|
|
@@ -132,6 +133,82 @@ export class Organization extends BaseEntity {
|
|
|
132
133
|
return super.getSubscribers(data);
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Récupérer les membres de l'organisation.
|
|
138
|
+
* Constant : GET_MEMBERS_ADMIN / GET_MEMBERS_NO_ADMIN
|
|
139
|
+
* @param {Object} data - Les données de requête.
|
|
140
|
+
* @param {Object} options - Options supplémentaires.
|
|
141
|
+
* @param {boolean} options.isAdmin - Indique si l'utilisateur est admin.
|
|
142
|
+
* @param {boolean} options.isInviting - Indique si l'utilisateur est en attente d'invitation.
|
|
143
|
+
* @param {Array} options.roles - Liste des rôles à filtrer.
|
|
144
|
+
* @returns {Promise<Object>} - Un objet contenant le nombre de membres et la liste des membres.
|
|
145
|
+
*/
|
|
146
|
+
async getMembers(data = {}, options = {}) {
|
|
147
|
+
const { isAdmin, isInviting, roles = [] } = options;
|
|
148
|
+
|
|
149
|
+
if(this.isMe){
|
|
150
|
+
data.pathParams = { type: this.getEntityType(), id: this.id };
|
|
151
|
+
// NOTE : dans le schema je crois que si pas de data.filters alors le default ce fait avec data.pathParams
|
|
152
|
+
// data.filters = {
|
|
153
|
+
// [`links.memberOf.${this.id}`]: { "$exists": true },
|
|
154
|
+
// [`links.memberOf.${this.id}.toBeValidated`]: { "$exists": false },
|
|
155
|
+
// [`links.memberOf.${this.id}.isInviting`]: { "$exists": false }
|
|
156
|
+
// };
|
|
157
|
+
} else {
|
|
158
|
+
delete data?.pathParams;
|
|
159
|
+
data.filters = this._buildMemberFilters(this.id, { isAdmin, isInviting, roles });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const fetchFn = this.isMe
|
|
163
|
+
? () => this.callIsMe(() => this.endpointApi.getMembersAdmin(data))
|
|
164
|
+
: () => this.endpointApi.getMembersNoAdmin(data);
|
|
165
|
+
|
|
166
|
+
const arrayObjet = await fetchFn();
|
|
167
|
+
if (!Array.isArray(arrayObjet.results)) {
|
|
168
|
+
throw new ApiResponseError("Erreur lors de la récupération des membres", 500, arrayObjet.results);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// lier les entités au objets
|
|
172
|
+
const rawList = this._linkEntities(arrayObjet.results);
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
count: arrayObjet.count?.poi ?? 0,
|
|
176
|
+
results: rawList
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
_buildMemberFilters(id, { isAdmin, isInviting, roles }) {
|
|
181
|
+
|
|
182
|
+
if (typeof isAdmin !== "undefined" && typeof isAdmin !== "boolean") {
|
|
183
|
+
throw new TypeError("isAdmin doit être un booléen.");
|
|
184
|
+
}
|
|
185
|
+
if (typeof isInviting !== "undefined" && typeof isInviting !== "boolean") {
|
|
186
|
+
throw new TypeError("isInviting doit être un booléen.");
|
|
187
|
+
}
|
|
188
|
+
if (!Array.isArray(roles)) {
|
|
189
|
+
throw new TypeError("roles doit être un tableau de chaînes.");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const filters = {
|
|
193
|
+
[`links.memberOf.${id}`]: { $exists: true },
|
|
194
|
+
[`links.memberOf.${id}.toBeValidated`]: { $exists: false }
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
if (isInviting === true || isInviting === false) {
|
|
198
|
+
filters[`links.memberOf.${id}.isInviting`] = { $exists: isInviting };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (isAdmin === true) {
|
|
202
|
+
filters[`links.memberOf.${id}.isAdmin`] = { $exists: true };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (Array.isArray(roles) && roles.length > 0) {
|
|
206
|
+
filters[`links.memberOf.${id}.roles`] = { $in: roles };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return filters;
|
|
210
|
+
}
|
|
211
|
+
|
|
135
212
|
/**
|
|
136
213
|
* Crée une instance de projet et récupère son profil si nécessaire.
|
|
137
214
|
*
|
package/src/api/User.js
CHANGED
|
@@ -25,29 +25,14 @@ export class User extends BaseEntity {
|
|
|
25
25
|
["PROFIL_IMAGE", "updateImageProfil"]
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Champs par défaut pour les schemas json ou l'on extrait les fields. (pour les if/else/then)
|
|
30
|
-
*
|
|
31
|
-
* @property {Object} defaultFields - Un objet contenant les propriétés par défaut pour l'entité User.
|
|
32
|
-
*/
|
|
33
28
|
defaultFields = {
|
|
34
29
|
typeElement: this.getEntityType(),
|
|
35
30
|
};
|
|
36
31
|
|
|
37
|
-
/**
|
|
38
|
-
* Champs à supprimer de draft lors de la construction du proxy.
|
|
39
|
-
*
|
|
40
|
-
* @property {Array<string>} removeFields - Un tableau de chaînes représentant les champs à supprimer.
|
|
41
|
-
*/
|
|
42
32
|
removeFields = [
|
|
43
33
|
"typeElement",
|
|
44
34
|
];
|
|
45
35
|
|
|
46
|
-
/**
|
|
47
|
-
* Transformateurs appliqués lors de la lecture du draft.
|
|
48
|
-
*
|
|
49
|
-
* @type {Object<string, function>}
|
|
50
|
-
*/
|
|
51
36
|
transforms = {
|
|
52
37
|
github: (val, full) => full?.socialNetwork?.github,
|
|
53
38
|
gitlab: (val, full) => full?.socialNetwork?.gitlab,
|
|
@@ -95,8 +80,6 @@ export class User extends BaseEntity {
|
|
|
95
80
|
if (!deps.News) throw new ApiError("News class must be injected.");
|
|
96
81
|
|
|
97
82
|
super(parent, data, deps);
|
|
98
|
-
|
|
99
|
-
// this.__entityTag = "User";
|
|
100
83
|
}
|
|
101
84
|
|
|
102
85
|
get slug() {
|
|
@@ -121,7 +104,7 @@ export class User extends BaseEntity {
|
|
|
121
104
|
this._setData(data);
|
|
122
105
|
return data;
|
|
123
106
|
} else {
|
|
124
|
-
const data = await this.
|
|
107
|
+
const data = await this._getPublicProfile();
|
|
125
108
|
this._setData(data);
|
|
126
109
|
return data;
|
|
127
110
|
}
|
|
@@ -318,26 +301,24 @@ export class User extends BaseEntity {
|
|
|
318
301
|
};
|
|
319
302
|
}
|
|
320
303
|
|
|
321
|
-
const
|
|
304
|
+
const arrayObjet = await fetchFn();
|
|
322
305
|
|
|
323
|
-
if (!Array.isArray(
|
|
324
|
-
throw new ApiResponseError("Erreur lors de la récupération des organisations.", 500,
|
|
306
|
+
if (!Array.isArray(arrayObjet.results)) {
|
|
307
|
+
throw new ApiResponseError("Erreur lors de la récupération des organisations.", 500, arrayObjet.results);
|
|
325
308
|
}
|
|
326
309
|
|
|
327
310
|
// nettoyage du count
|
|
328
|
-
delete
|
|
311
|
+
delete arrayObjet?.count?.spam;
|
|
329
312
|
|
|
330
313
|
// calcul du total
|
|
331
|
-
const totalCount = Object.values(
|
|
332
|
-
|
|
314
|
+
const totalCount = Object.values(arrayObjet.count || {}).reduce((acc, val) => acc + val, 0);
|
|
315
|
+
arrayObjet.count.total = totalCount;
|
|
333
316
|
|
|
334
|
-
const
|
|
335
|
-
(d) => this.linkEntity?.(d.collection, d) ?? d
|
|
336
|
-
);
|
|
317
|
+
const rawList = this._linkEntities(arrayObjet.results);
|
|
337
318
|
|
|
338
319
|
return {
|
|
339
|
-
count:
|
|
340
|
-
results:
|
|
320
|
+
count: arrayObjet.count,
|
|
321
|
+
results: rawList
|
|
341
322
|
};
|
|
342
323
|
}
|
|
343
324
|
|
|
@@ -379,19 +360,17 @@ export class User extends BaseEntity {
|
|
|
379
360
|
data.pathParams = { id: this.id };
|
|
380
361
|
}
|
|
381
362
|
|
|
382
|
-
const
|
|
383
|
-
if(!Array.isArray(
|
|
384
|
-
throw new ApiResponseError("Erreur lors de la récupération des amis administrables.", 500,
|
|
363
|
+
const arrayObjet = await this.endpointApi.getFriendsAdmin(data);
|
|
364
|
+
if(!Array.isArray(arrayObjet.results)){
|
|
365
|
+
throw new ApiResponseError("Erreur lors de la récupération des amis administrables.", 500, arrayObjet);
|
|
385
366
|
|
|
386
367
|
}
|
|
387
368
|
|
|
388
|
-
const
|
|
389
|
-
(d) => this.linkEntity?.(d.collection, d) ?? d
|
|
390
|
-
);
|
|
369
|
+
const rawList = this._linkEntities(arrayObjet.results);
|
|
391
370
|
|
|
392
371
|
return {
|
|
393
|
-
count:
|
|
394
|
-
results:
|
|
372
|
+
count: arrayObjet?.count?.citoyens ?? 0,
|
|
373
|
+
results: rawList
|
|
395
374
|
};
|
|
396
375
|
}
|
|
397
376
|
|
|
@@ -412,19 +391,17 @@ export class User extends BaseEntity {
|
|
|
412
391
|
};
|
|
413
392
|
}
|
|
414
393
|
|
|
415
|
-
const
|
|
416
|
-
if (!Array.isArray(
|
|
417
|
-
throw new ApiResponseError("Erreur lors de la récupération des abonnements.", 500,
|
|
394
|
+
const arrayObjet = await fetchFn();
|
|
395
|
+
if (!Array.isArray(arrayObjet.results)) {
|
|
396
|
+
throw new ApiResponseError("Erreur lors de la récupération des abonnements.", 500, arrayObjet.results);
|
|
418
397
|
}
|
|
419
398
|
|
|
420
399
|
// lier les entités au objets
|
|
421
|
-
const
|
|
422
|
-
(d) => this.linkEntity?.(d.collection, d) ?? d
|
|
423
|
-
);
|
|
400
|
+
const rawList = this._linkEntities(arrayObjet.results);
|
|
424
401
|
|
|
425
402
|
return {
|
|
426
|
-
count:
|
|
427
|
-
results:
|
|
403
|
+
count: arrayObjet.count,
|
|
404
|
+
results: rawList
|
|
428
405
|
};
|
|
429
406
|
}
|
|
430
407
|
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// DraftStateMixin.js
|
|
2
|
-
import { ApiError, ApiValidationError } from "../error.js";
|
|
3
|
-
|
|
4
|
-
export const DraftStateMixin = {
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Crée un proxy combinant draft + serveur, avec transformations facultatives.
|
|
8
|
-
* @param {Object} server
|
|
9
|
-
* @param {Object} draft
|
|
10
|
-
* @param {Array} allowedFields - champs autorisés dans le draft
|
|
11
|
-
* @param {Object} [transforms={}] - transformateurs de lecture
|
|
12
|
-
* @param {Object} [options={}] - options
|
|
13
|
-
* @returns {Proxy}
|
|
14
|
-
*/
|
|
15
|
-
_createDraftProxy(apiClient, server = {}, draft = {}, allowedFields = [], transforms = {}, options = {}) {
|
|
16
|
-
return new Proxy({}, {
|
|
17
|
-
get: (_, prop) => {
|
|
18
|
-
const val = prop in draft ? draft[prop] : server[prop];
|
|
19
|
-
const transformer = transforms[prop];
|
|
20
|
-
return typeof transformer === "function" ? transformer(val) : val;
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
set: (_, prop, value) => {
|
|
24
|
-
if (!allowedFields.includes(prop)) {
|
|
25
|
-
const message = `[DraftProxy] Le champ "${prop}" n'est pas autorisé.`;
|
|
26
|
-
if (options.throwOnError) {
|
|
27
|
-
throw new ApiValidationError(message, 400, null, {
|
|
28
|
-
field: prop,
|
|
29
|
-
value,
|
|
30
|
-
allowedFields
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
apiClient._logger.warn(message);
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
draft[prop] = value;
|
|
37
|
-
return true;
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
deleteProperty: (_, prop) => {
|
|
41
|
-
if (!allowedFields.includes(prop)) return false;
|
|
42
|
-
delete draft[prop];
|
|
43
|
-
return true;
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
has: (_, prop) => prop in draft || prop in server,
|
|
47
|
-
ownKeys: () => [...new Set([...Object.keys(server), ...Object.keys(draft)])],
|
|
48
|
-
getOwnPropertyDescriptor: () => ({ enumerable: true, configurable: true })
|
|
49
|
-
});
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
_extractWritableFields(schema = {}, data = {}, ctx = { defs: {}, visited: new Set() }) {
|
|
53
|
-
if (!schema || typeof schema !== "object") return [];
|
|
54
|
-
if (schema.$id && ctx.visited.has(schema.$id)) return [];
|
|
55
|
-
if (schema.$id) ctx.visited.add(schema.$id);
|
|
56
|
-
ctx.defs = schema.$defs || schema.definitions || ctx.defs;
|
|
57
|
-
|
|
58
|
-
const fields = [];
|
|
59
|
-
|
|
60
|
-
if (schema.$ref) {
|
|
61
|
-
const refKey = schema.$ref.replace(/^#\/?(\$defs|definitions)\//, "");
|
|
62
|
-
const resolved = ctx.defs?.[refKey];
|
|
63
|
-
if (resolved) fields.push(...this._extractWritableFields(resolved, data, ctx));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (schema.allOf) {
|
|
67
|
-
schema.allOf.forEach(s => fields.push(...this._extractWritableFields(s, data, ctx)));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (schema.if && schema.then) {
|
|
71
|
-
const condition = schema.if?.properties;
|
|
72
|
-
let matches = true;
|
|
73
|
-
if (condition) {
|
|
74
|
-
for (const key in condition) {
|
|
75
|
-
const expected = condition[key]?.const;
|
|
76
|
-
if (data[key] !== expected) {
|
|
77
|
-
matches = false;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (matches && schema.then) {
|
|
83
|
-
fields.push(...this._extractWritableFields(schema.then, data, ctx));
|
|
84
|
-
} else if (!matches && schema.else) {
|
|
85
|
-
fields.push(...this._extractWritableFields(schema.else, data, ctx));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (schema.properties) {
|
|
90
|
-
fields.push(...Object.entries(schema.properties)
|
|
91
|
-
// eslint-disable-next-line no-unused-vars
|
|
92
|
-
.filter(([_, def]) => def.readOnly !== true && def.const === undefined)
|
|
93
|
-
.map(([key]) => key));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return [...new Set(fields)];
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
_buildDraftAndProxy({ data = {}, serverData = null, constant, apiClient, transforms = {}, throwOnError = true, removeFields = [] }) {
|
|
100
|
-
const constants = Array.isArray(constant) ? constant : [constant];
|
|
101
|
-
const combinedSchema = {
|
|
102
|
-
allOf: [],
|
|
103
|
-
$defs: {}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
for (const key of constants) {
|
|
107
|
-
const sch = apiClient.getRequestSchema(key);
|
|
108
|
-
if (!sch) throw new ApiError(`Unable to find schema for ${key}.`);
|
|
109
|
-
|
|
110
|
-
// Extraire et fusionner les $defs
|
|
111
|
-
if (sch.$defs) {
|
|
112
|
-
for (const [defKey, defVal] of Object.entries(sch.$defs)) {
|
|
113
|
-
if (combinedSchema.$defs[defKey]) {
|
|
114
|
-
apiClient._logger.warn(`Duplicate $defs key '${defKey}' from schema '${key}'`);
|
|
115
|
-
} else {
|
|
116
|
-
combinedSchema.$defs[defKey] = defVal;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
combinedSchema.allOf.push(sch);
|
|
122
|
-
}
|
|
123
|
-
const draft = {};
|
|
124
|
-
let allowed = this._extractWritableFields(combinedSchema, data);
|
|
125
|
-
|
|
126
|
-
if (data.id && allowed.indexOf("id") === -1) {
|
|
127
|
-
allowed.push("id");
|
|
128
|
-
}
|
|
129
|
-
if (data.slug && allowed.indexOf("slug") === -1) {
|
|
130
|
-
allowed.push("slug");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
allowed = allowed.filter(k => !removeFields.includes(k));
|
|
134
|
-
|
|
135
|
-
for (const key of allowed) {
|
|
136
|
-
const raw = data[key];
|
|
137
|
-
const transformed = typeof transforms[key] === "function" ? transforms[key](raw, data) : raw;
|
|
138
|
-
if (transformed !== undefined) draft[key] = transformed;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const proxy = this._createDraftProxy(apiClient, serverData, draft, allowed, transforms, { throwOnError });
|
|
142
|
-
|
|
143
|
-
return { draft, proxy };
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
_extractChangedFieldsFromSchema(apiClient, constant, data = {}, getInitialDraft, removeFields = []) {
|
|
147
|
-
const schema = apiClient.getRequestSchema(constant);
|
|
148
|
-
let allowed = this._extractWritableFields(schema, data);
|
|
149
|
-
const changed = {};
|
|
150
|
-
const initialDraft = getInitialDraft?.() || {};
|
|
151
|
-
|
|
152
|
-
// on enlève les champs qui ne sont pas dans le draft
|
|
153
|
-
// ou qui sont dans removeFields
|
|
154
|
-
allowed = allowed.filter(k => !removeFields.includes(k));
|
|
155
|
-
|
|
156
|
-
for (const key of allowed) {
|
|
157
|
-
// on verifie que le champ existe dans le draft
|
|
158
|
-
// sinon on ne le prend pas en compte
|
|
159
|
-
|
|
160
|
-
if (data[key] === undefined) continue;
|
|
161
|
-
|
|
162
|
-
const current = data[key];
|
|
163
|
-
const initial = initialDraft[key];
|
|
164
|
-
|
|
165
|
-
const changedValue =
|
|
166
|
-
JSON.stringify(current) !== JSON.stringify(initial);
|
|
167
|
-
|
|
168
|
-
if (changedValue) {
|
|
169
|
-
changed[key] = current;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return Object.keys(changed).length > 0 ? changed : null;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
};
|