@communecter/cocolight-api-client 1.0.56 → 1.0.58
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.ts +21 -13
- package/src/ApiClient.ts +2 -1
- package/src/api/Answer.ts +69 -0
- package/src/api/BaseEntity.ts +26 -9
- package/src/api/EndpointApi.ts +31 -1
- package/src/api/EndpointApi.types.ts +161 -1
- package/src/api/EntityRegistry.ts +10 -3
- package/src/api/News.ts +2 -4
- package/src/api/Organization.ts +10 -1
- package/src/api/User.ts +42 -1
- package/src/api/serverDataType/Answer.ts +54 -0
- package/src/endpoints.module.ts +97 -8
- package/src/index.ts +6 -0
- package/src/types/entities.ts +25 -1
- package/src/utils/reactive.ts +4 -0
- package/types/Api.d.ts +8 -23
- package/types/api/Answer.d.ts +23 -0
- package/types/api/BaseEntity.d.ts +9 -5
- package/types/api/EndpointApi.d.ts +19 -1
- package/types/api/EndpointApi.types.d.ts +155 -1
- package/types/api/EntityRegistry.d.ts +1 -1
- package/types/api/Organization.d.ts +8 -3
- package/types/api/Project.d.ts +1 -1
- package/types/api/User.d.ts +5 -0
- package/types/api/serverDataType/Answer.d.ts +50 -0
- package/types/endpoints.module.d.ts +330 -10
- package/types/index.d.ts +6 -0
- package/types/types/entities.d.ts +28 -1
package/package.json
CHANGED
package/src/Api.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Api.ts
|
|
2
|
+
import { Answer } from "./api/Answer.js";
|
|
2
3
|
import { Badge } from "./api/Badge.js";
|
|
3
4
|
import { Comment } from "./api/Comment.js";
|
|
4
5
|
import EndpointApi from "./api/EndpointApi.js";
|
|
@@ -15,6 +16,7 @@ import { ApiAuthenticationError, ApiClientError, ApiError, ApiResponseError } fr
|
|
|
15
16
|
import type ApiClient from "./ApiClient.js";
|
|
16
17
|
import type { ApiClientOptions } from "./ApiClient.js";
|
|
17
18
|
import type { GetElementsKeyResponse } from "./types/api-responses.js";
|
|
19
|
+
import type { EntityData, EntityTypes } from "./types/entities.js";
|
|
18
20
|
|
|
19
21
|
registerEntity("User", User);
|
|
20
22
|
registerEntity("Organization", Organization);
|
|
@@ -26,20 +28,9 @@ registerEntity("EndpointApi", EndpointApi);
|
|
|
26
28
|
// registerEntity("UserApi", UserApi);
|
|
27
29
|
registerEntity("News", News);
|
|
28
30
|
registerEntity("Comment", Comment);
|
|
31
|
+
registerEntity("Answer", Answer);
|
|
29
32
|
|
|
30
|
-
/**
|
|
31
|
-
* Union type for all possible entity types
|
|
32
|
-
*/
|
|
33
|
-
type EntityTypes = User | Organization | Project | Event | Poi | Badge | News | Comment;
|
|
34
33
|
|
|
35
|
-
/**
|
|
36
|
-
* Type pour récupérer une entité existante via l'API publique.
|
|
37
|
-
* Nécessite soit un id, soit un slug.
|
|
38
|
-
* Les propriétés additionnelles sont autorisées mais ignorées lors de la récupération.
|
|
39
|
-
*/
|
|
40
|
-
type EntityData =
|
|
41
|
-
| { id: string; slug?: string; [key: string]: any }
|
|
42
|
-
| { slug: string; id?: string; [key: string]: any };
|
|
43
34
|
|
|
44
35
|
export default class Api {
|
|
45
36
|
private _loggedUser: User | null;
|
|
@@ -153,7 +144,7 @@ export default class Api {
|
|
|
153
144
|
*/
|
|
154
145
|
async organization(organizationData: EntityData): Promise<Organization> {
|
|
155
146
|
try {
|
|
156
|
-
const organization = new Organization(this._client, organizationData, { EndpointApi, User, Project, Event, Poi, Badge, News, Comment });
|
|
147
|
+
const organization = new Organization(this._client, organizationData, { EndpointApi, User, Project, Event, Poi, Badge, News, Comment, Answer });
|
|
157
148
|
if (!organizationData.id && !organizationData.slug) {
|
|
158
149
|
throw new Error("Vous devez fournir un id ou un slug pour créer une instance Organization.");
|
|
159
150
|
}
|
|
@@ -199,6 +190,23 @@ export default class Api {
|
|
|
199
190
|
}
|
|
200
191
|
}
|
|
201
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Creates a new Answer instance and optionally retrieves answer data.
|
|
195
|
+
*/
|
|
196
|
+
async answer(answerData: { id: string }): Promise<Answer> {
|
|
197
|
+
try {
|
|
198
|
+
const answer = new Answer(this._client, answerData, { EndpointApi, User, Organization, Project, Event, Poi, Badge, News, Comment });
|
|
199
|
+
if (!answerData.id) {
|
|
200
|
+
throw new Error("Vous devez fournir un id pour créer une instance Answer.");
|
|
201
|
+
}
|
|
202
|
+
await answer.get();
|
|
203
|
+
return answer;
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error("[Api.answer] Erreur lors de la création d'un objet Answer :", (error as Error).message);
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
202
210
|
/**
|
|
203
211
|
* Retourne une entité à partir d'un slug.
|
|
204
212
|
*/
|
package/src/ApiClient.ts
CHANGED
|
@@ -844,10 +844,11 @@ export default class ApiClient extends EventEmitter {
|
|
|
844
844
|
headers,
|
|
845
845
|
[lowerMethod === "get" ? "params" : "data"]: payload
|
|
846
846
|
});
|
|
847
|
-
|
|
847
|
+
|
|
848
848
|
if (validateResponseSchema) {
|
|
849
849
|
const statusStr = String(response.status);
|
|
850
850
|
const schema = responses?.[statusStr];
|
|
851
|
+
|
|
851
852
|
if (schema) {
|
|
852
853
|
const validateResponse: ValidateFunction = this._ajv.compile(schema);
|
|
853
854
|
const valid = validateResponse(response.data);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { BaseEntity } from "./BaseEntity.js";
|
|
2
|
+
import { ApiError } from "../error.js";
|
|
3
|
+
|
|
4
|
+
import type { AnswerItemNormalized } from "./serverDataType/Answer.js";
|
|
5
|
+
|
|
6
|
+
export class Answer extends BaseEntity<AnswerItemNormalized> {
|
|
7
|
+
static override entityType = "answers";
|
|
8
|
+
|
|
9
|
+
static override entityTag = "Answer";
|
|
10
|
+
static override SCHEMA_CONSTANTS: string[] = [
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
static ADD_BLOCKS: Map<string, string> = new Map([
|
|
14
|
+
]);
|
|
15
|
+
static UPDATE_BLOCKS: Map<string, string> = new Map([
|
|
16
|
+
]);
|
|
17
|
+
override defaultFields: Record<string, any> = {
|
|
18
|
+
};
|
|
19
|
+
override removeFields: string[] = [];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Transforme les champs imbriqués (user, context etc.) en instances d'entités.
|
|
23
|
+
* @param data - Les données brutes du serveur.
|
|
24
|
+
* @returns Les données transformées.
|
|
25
|
+
* @protected
|
|
26
|
+
*/
|
|
27
|
+
protected override _transformServerData(data: AnswerItemNormalized): AnswerItemNormalized {
|
|
28
|
+
|
|
29
|
+
// Transformer user en instance User
|
|
30
|
+
if(data.user && typeof data.user === "object" && "id" in data.user) {
|
|
31
|
+
data.user = this._linkNestedEntity({ id: (data.user as any).id, type: "citoyens" });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Transformer context en instance Organization/Project
|
|
35
|
+
// if (data.context && typeof data.context === "object" && !("id" in data.context)) {
|
|
36
|
+
// // context est un ParentsMap: { "id1": {type: "organizations", name: "..."}, "id2": {...} }
|
|
37
|
+
// // On transforme chaque entrée en instance d'entité
|
|
38
|
+
// const transformedContext: Record<string, any> = {};
|
|
39
|
+
// for (const [id, parentRef] of Object.entries(data.context)) {
|
|
40
|
+
// if (parentRef && typeof parentRef === "object" && "type" in parentRef) {
|
|
41
|
+
// transformedContext[id] = this._linkNestedEntity({ id, type: parentRef.type });
|
|
42
|
+
// }
|
|
43
|
+
// }
|
|
44
|
+
// data.context = transformedContext;
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Rafraîchit les données de l'entité depuis l'API.
|
|
52
|
+
* Constant : COFORM_ANSWERS_BY_ID
|
|
53
|
+
*/
|
|
54
|
+
override async get(): Promise<Record<string, any>> {
|
|
55
|
+
if (!this.id) throw new ApiError("Impossible de rafraîchir sans ID.", 400);
|
|
56
|
+
const answerId = this.id; // Type narrowing
|
|
57
|
+
|
|
58
|
+
const answer = await this.endpointApi.coformAnswersById({
|
|
59
|
+
answerId
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (answer?.data?.id) {
|
|
63
|
+
this._setData(answer.data as AnswerItemNormalized, { forceInitialDraftReset: true });
|
|
64
|
+
return this.serverData;
|
|
65
|
+
}
|
|
66
|
+
throw new ApiError(`Aucune réponse trouvée pour l'ID ${this.id}`, 404);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
}
|
package/src/api/BaseEntity.ts
CHANGED
|
@@ -39,7 +39,8 @@ import type {
|
|
|
39
39
|
GetPoisAdminData,
|
|
40
40
|
GetPoisNoAdminData,
|
|
41
41
|
GetSubscribersData,
|
|
42
|
-
GetBadgesData
|
|
42
|
+
GetBadgesData,
|
|
43
|
+
CoformAnswersSearchData
|
|
43
44
|
} from "./EndpointApi.types.js";
|
|
44
45
|
import type { GetElementsKeyResponse } from "../types/api-responses.js";
|
|
45
46
|
import type { TransformsMap } from "../types/entities.js";
|
|
@@ -74,9 +75,10 @@ type Poi = import("./Poi.js").Poi;
|
|
|
74
75
|
type News = import("./News.js").News;
|
|
75
76
|
type Badge = import("./Badge.js").Badge;
|
|
76
77
|
type Comment = import("./Comment.js").Comment;
|
|
78
|
+
type Answer = import("./Answer.js").Answer;
|
|
77
79
|
|
|
78
80
|
// Types d'union
|
|
79
|
-
type AnyEntity = User | Organization | Project | Poi | EventEntity | Badge | News | Comment;
|
|
81
|
+
type AnyEntity = User | Organization | Project | Poi | EventEntity | Badge | News | Comment | Answer;
|
|
80
82
|
type ParentLike = BaseEntity<any> & { apiClient: ApiClient, userContext?: User | null };
|
|
81
83
|
|
|
82
84
|
// Types pour les dépendances
|
|
@@ -93,6 +95,7 @@ interface Deps {
|
|
|
93
95
|
Badge?: any;
|
|
94
96
|
News?: any;
|
|
95
97
|
Comment?: any;
|
|
98
|
+
Answer?: any;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
interface BaseEntityConfig {
|
|
@@ -109,6 +112,7 @@ interface EntityTypeMap {
|
|
|
109
112
|
news: News;
|
|
110
113
|
badges: Badge;
|
|
111
114
|
comments: Comment;
|
|
115
|
+
answers: Answer;
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
// Types pour les streams et uploads
|
|
@@ -158,7 +162,7 @@ interface LinkMeta {
|
|
|
158
162
|
// Type du constructeur de BaseEntity avec ses propriétés statiques
|
|
159
163
|
type BaseEntityCtor = typeof BaseEntity & {
|
|
160
164
|
entityTag: string;
|
|
161
|
-
entityType: "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news" | "comments";
|
|
165
|
+
entityType: "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news" | "comments" | "answers";
|
|
162
166
|
SCHEMA_CONSTANTS: string | string[];
|
|
163
167
|
};
|
|
164
168
|
|
|
@@ -261,7 +265,7 @@ interface FinalizerResult<TOut> {
|
|
|
261
265
|
}
|
|
262
266
|
|
|
263
267
|
// Types pour les entités
|
|
264
|
-
type EntityType = "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news";
|
|
268
|
+
type EntityType = "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news" | "comments" | "answers";
|
|
265
269
|
|
|
266
270
|
// ============================================================================
|
|
267
271
|
|
|
@@ -440,7 +444,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
440
444
|
}
|
|
441
445
|
|
|
442
446
|
/** @returns Type de l'entité (ex: 'citoyens') */
|
|
443
|
-
getEntityType(): "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news" | "comments" {
|
|
447
|
+
getEntityType(): "citoyens" | "organizations" | "projects" | "events" | "poi" | "badges" | "news" | "comments" | "answers" {
|
|
444
448
|
return this._getCtor().entityType;
|
|
445
449
|
}
|
|
446
450
|
|
|
@@ -1693,6 +1697,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
1693
1697
|
Badge: selfTag === "Badge" ? selfClass : this.deps.Badge,
|
|
1694
1698
|
News: selfTag === "News" ? selfClass : this.deps.News,
|
|
1695
1699
|
Comment: selfTag === "Comment" ? selfClass : this.deps.Comment,
|
|
1700
|
+
Answer: selfTag === "Answer" ? selfClass : this.deps.Answer,
|
|
1696
1701
|
};
|
|
1697
1702
|
|
|
1698
1703
|
const map = {
|
|
@@ -1709,6 +1714,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
1709
1714
|
Project: commonDeps.Project
|
|
1710
1715
|
} },
|
|
1711
1716
|
comments: { entityClass: commonDeps.Comment, deps: { ...commonDeps } },
|
|
1717
|
+
answers: { entityClass: commonDeps.Answer, deps: { ...commonDeps } },
|
|
1712
1718
|
};
|
|
1713
1719
|
|
|
1714
1720
|
return (map as Record<string, EntityMeta | undefined>)[entityType] || null;
|
|
@@ -1939,6 +1945,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
1939
1945
|
news: ["id"],
|
|
1940
1946
|
badges: ["id"],
|
|
1941
1947
|
comments: [], // Pas de get() pour les commentaires
|
|
1948
|
+
answers: ["id"],
|
|
1942
1949
|
};
|
|
1943
1950
|
|
|
1944
1951
|
const fetchKeys = (fetchKeysByEntity as Record<string, string[] | undefined>)[entityType];
|
|
@@ -2565,7 +2572,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
2565
2572
|
|
|
2566
2573
|
// Réduit le type de l'entité aux seuls autorisés par UpdateBlockLocalityData
|
|
2567
2574
|
const t = this.getEntityType();
|
|
2568
|
-
if (t === "badges" || t === "news" || t === "comments") {
|
|
2575
|
+
if (t === "badges" || t === "news" || t === "comments" || t === "answers") {
|
|
2569
2576
|
throw new ApiError(`Le type d'entité "${t}" n'est pas supporté par UPDATE_BLOCK_LOCALITY.`, 400);
|
|
2570
2577
|
}
|
|
2571
2578
|
|
|
@@ -2646,7 +2653,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
2646
2653
|
}
|
|
2647
2654
|
|
|
2648
2655
|
const t = this.getEntityType();
|
|
2649
|
-
if (t === "badges" || t === "news" || t === "comments") {
|
|
2656
|
+
if (t === "badges" || t === "news" || t === "comments" || t === "answers") {
|
|
2650
2657
|
throw new ApiError(`Le type d'entité "${t}" n'est pas supporté par UPDATE_BLOCK_LOCALITY.`, 400);
|
|
2651
2658
|
}
|
|
2652
2659
|
|
|
@@ -2959,7 +2966,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
2959
2966
|
}
|
|
2960
2967
|
|
|
2961
2968
|
const t = this.getEntityType();
|
|
2962
|
-
if (t === "badges" || t === "news" || t === "poi" || t === "events" || t === "comments") {
|
|
2969
|
+
if (t === "badges" || t === "news" || t === "poi" || t === "events" || t === "comments" || t === "answers") {
|
|
2963
2970
|
throw new ApiError(`Le type d'entité "${t}" n'est pas supporté par GET_NEWS.`, 400);
|
|
2964
2971
|
}
|
|
2965
2972
|
|
|
@@ -3001,7 +3008,7 @@ export class BaseEntity<TServerData = any> {
|
|
|
3001
3008
|
}
|
|
3002
3009
|
|
|
3003
3010
|
const t = this.getEntityType();
|
|
3004
|
-
if (t === "badges" || t === "news" || t === "poi" || t === "events" || t === "comments") {
|
|
3011
|
+
if (t === "badges" || t === "news" || t === "poi" || t === "events" || t === "comments" || t === "answers") {
|
|
3005
3012
|
throw new ApiError(`Le type d'entité "${t}" n'est pas supporté par UPDATE_BLOCK_LOCALITY.`, 400);
|
|
3006
3013
|
}
|
|
3007
3014
|
|
|
@@ -3884,6 +3891,16 @@ export class BaseEntity<TServerData = any> {
|
|
|
3884
3891
|
return wrappedFinalizer(fullData);
|
|
3885
3892
|
}
|
|
3886
3893
|
|
|
3894
|
+
|
|
3895
|
+
async coformAnswersSearch(data: Partial<CoformAnswersSearchData> = {}): Promise<PaginatorPage<any>> {
|
|
3896
|
+
const paginator = this._createPaginatorEngine({
|
|
3897
|
+
initialData: data,
|
|
3898
|
+
finalizer: this._withCostumContext(
|
|
3899
|
+
(finalData: CoformAnswersSearchData) => this.endpointApi.coformAnswersSearch(finalData)
|
|
3900
|
+
),
|
|
3901
|
+
});
|
|
3902
|
+
return paginator.next() as Promise<PaginatorPage<any>>;
|
|
3903
|
+
}
|
|
3887
3904
|
|
|
3888
3905
|
}
|
|
3889
3906
|
|
package/src/api/EndpointApi.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { ApiAuthenticationError } from "../error.js";
|
|
3
3
|
|
|
4
4
|
import type ApiClient from "../ApiClient.js";
|
|
5
|
-
import type { PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, GetElementsAboutData, MulticonnectData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeletePoiData, DeleteEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, ShareEventsData, InviteEventData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData } from "./EndpointApi.types.js";
|
|
5
|
+
import type { PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, GetElementsAboutData, MulticonnectData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeletePoiData, DeleteEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, ShareEventsData, InviteEventData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData } from "./EndpointApi.types.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Classe EndpointApi générée automatiquement depuis endpoints-copie.json
|
|
@@ -1594,6 +1594,36 @@ export class EndpointApi {
|
|
|
1594
1594
|
return this.callIsConnected("GET_ATTENDEES_ADMIN", data);
|
|
1595
1595
|
}
|
|
1596
1596
|
|
|
1597
|
+
/**
|
|
1598
|
+
* Recherche des reponses des formulaires basées sur un coform : Effectue une recherche des reponses des formulaires basées sur un coform
|
|
1599
|
+
* Constant : COFORM_ANSWERS_SEARCH
|
|
1600
|
+
* @param data - Données envoyées à l'API
|
|
1601
|
+
* @returns Les données de réponse.
|
|
1602
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
1603
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
1604
|
+
*/
|
|
1605
|
+
async coformAnswersSearch(data: CoformAnswersSearchData): Promise<any> {
|
|
1606
|
+
if (!data || typeof data !== "object") {
|
|
1607
|
+
throw new TypeError("Le paramètre data doit être un objet.");
|
|
1608
|
+
}
|
|
1609
|
+
return this.call("COFORM_ANSWERS_SEARCH", data);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
/**
|
|
1613
|
+
* Récuperer une réponse de formulaire par son ID : Récuperer une réponse de formulaire par son ID
|
|
1614
|
+
* Constant : COFORM_ANSWERS_BY_ID
|
|
1615
|
+
* @param data - Données envoyées à l'API
|
|
1616
|
+
* @returns Les données de réponse.
|
|
1617
|
+
* @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
|
|
1618
|
+
* @throws {Error} - En cas d'erreur inattendue.
|
|
1619
|
+
*/
|
|
1620
|
+
async coformAnswersById(data: CoformAnswersByIdData): Promise<any> {
|
|
1621
|
+
if (!data || typeof data !== "object") {
|
|
1622
|
+
throw new TypeError("Le paramètre data doit être un objet.");
|
|
1623
|
+
}
|
|
1624
|
+
return this.call("COFORM_ANSWERS_BY_ID", data);
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1597
1627
|
}
|
|
1598
1628
|
|
|
1599
1629
|
export default EndpointApi;
|
|
@@ -413,7 +413,7 @@ export interface GetElementsAboutData {
|
|
|
413
413
|
/**
|
|
414
414
|
* Type d'entité
|
|
415
415
|
*/
|
|
416
|
-
type: "citoyens" | "projects" | "organizations" | "events" | "poi" | "badges";
|
|
416
|
+
type: "citoyens" | "projects" | "organizations" | "events" | "poi" | "badges" | "answers";
|
|
417
417
|
/**
|
|
418
418
|
* ID de l'utilisateur ou de l'entité
|
|
419
419
|
*/
|
|
@@ -4607,3 +4607,163 @@ export interface GetAttendeesAdminData {
|
|
|
4607
4607
|
};
|
|
4608
4608
|
[k: string]: unknown;
|
|
4609
4609
|
}
|
|
4610
|
+
|
|
4611
|
+
|
|
4612
|
+
export interface CoformAnswersSearchData {
|
|
4613
|
+
/**
|
|
4614
|
+
* Nom ou mot-clé de la recherche
|
|
4615
|
+
*/
|
|
4616
|
+
name?: string;
|
|
4617
|
+
/**
|
|
4618
|
+
* Liste des localités ciblées avec leur identifiant et leur type (city ou level1)
|
|
4619
|
+
*/
|
|
4620
|
+
locality?: {
|
|
4621
|
+
/**
|
|
4622
|
+
* This interface was referenced by `undefined`'s JSON-Schema definition
|
|
4623
|
+
* via the `patternProperty` "^[^\s]+$".
|
|
4624
|
+
*/
|
|
4625
|
+
[k: string]: {
|
|
4626
|
+
/**
|
|
4627
|
+
* Identifiant de la localité
|
|
4628
|
+
*/
|
|
4629
|
+
id: string;
|
|
4630
|
+
/**
|
|
4631
|
+
* Type de la localité : 'cities' pour une ville ou 'level1' pour une région
|
|
4632
|
+
*/
|
|
4633
|
+
type: "cities" | "level1";
|
|
4634
|
+
};
|
|
4635
|
+
};
|
|
4636
|
+
/**
|
|
4637
|
+
* Types d'entités à inclure dans la recherche
|
|
4638
|
+
*/
|
|
4639
|
+
searchType: "answers"[];
|
|
4640
|
+
/**
|
|
4641
|
+
* Balises (tags) à utiliser pour filtrer la recherche
|
|
4642
|
+
*/
|
|
4643
|
+
searchTags?: string[];
|
|
4644
|
+
/**
|
|
4645
|
+
* Liste fixe des types à compter dans les résultats
|
|
4646
|
+
*/
|
|
4647
|
+
countType: "answers"[];
|
|
4648
|
+
/**
|
|
4649
|
+
* Critère de recherche (actuellement vide)
|
|
4650
|
+
*/
|
|
4651
|
+
searchBy?: "ALL";
|
|
4652
|
+
/**
|
|
4653
|
+
* Index de départ global pour la pagination
|
|
4654
|
+
*/
|
|
4655
|
+
indexMin: number;
|
|
4656
|
+
/**
|
|
4657
|
+
* Index de fin global pour la pagination
|
|
4658
|
+
*/
|
|
4659
|
+
indexMax?: number;
|
|
4660
|
+
/**
|
|
4661
|
+
* Nombre d’éléments à récupérer (limite de pagination)
|
|
4662
|
+
*/
|
|
4663
|
+
indexStep: number;
|
|
4664
|
+
/**
|
|
4665
|
+
* Configuration des plages de résultats pour chaque type de recherche
|
|
4666
|
+
*/
|
|
4667
|
+
ranges?: {
|
|
4668
|
+
/**
|
|
4669
|
+
* This interface was referenced by `undefined`'s JSON-Schema definition
|
|
4670
|
+
* via the `patternProperty` "^[^\s]+$".
|
|
4671
|
+
*/
|
|
4672
|
+
[k: string]: {
|
|
4673
|
+
/**
|
|
4674
|
+
* Index de départ pour la pagination
|
|
4675
|
+
*/
|
|
4676
|
+
indexMin: number;
|
|
4677
|
+
/**
|
|
4678
|
+
* Index de fin pour la pagination
|
|
4679
|
+
*/
|
|
4680
|
+
indexMax: number;
|
|
4681
|
+
};
|
|
4682
|
+
};
|
|
4683
|
+
/**
|
|
4684
|
+
* Type initial de la recherche, vide par défaut
|
|
4685
|
+
*/
|
|
4686
|
+
initType: "";
|
|
4687
|
+
/**
|
|
4688
|
+
* Indique si les types doivent être comptés dans les résultats
|
|
4689
|
+
*/
|
|
4690
|
+
count: true;
|
|
4691
|
+
/**
|
|
4692
|
+
* Filtres additionnels appliqués à la recherche (objet ou chaîne vide)
|
|
4693
|
+
*/
|
|
4694
|
+
filters?:
|
|
4695
|
+
| {
|
|
4696
|
+
[k: string]: unknown;
|
|
4697
|
+
}
|
|
4698
|
+
| "";
|
|
4699
|
+
/**
|
|
4700
|
+
* Liste des champs à retourner
|
|
4701
|
+
*/
|
|
4702
|
+
fields?: string[];
|
|
4703
|
+
/**
|
|
4704
|
+
* Champ de tri (clé = champ, valeur = 1 ou -1)
|
|
4705
|
+
*/
|
|
4706
|
+
sortBy?: {
|
|
4707
|
+
[k: string]: 1 | -1;
|
|
4708
|
+
};
|
|
4709
|
+
/**
|
|
4710
|
+
* Indique si la recherche doit s'étendre au Fediverse (toujours désactivé)
|
|
4711
|
+
*/
|
|
4712
|
+
fediverse: boolean;
|
|
4713
|
+
/**
|
|
4714
|
+
* Indique si la recherche est effectuée à partir d'une carte (toujours désactivé)
|
|
4715
|
+
*/
|
|
4716
|
+
mapUsed?: true;
|
|
4717
|
+
/**
|
|
4718
|
+
* Indique si on doit exclure les éléments avec une source
|
|
4719
|
+
*/
|
|
4720
|
+
notSourceKey?: true;
|
|
4721
|
+
/**
|
|
4722
|
+
* ID du contexte de recherche (actuellement vide)
|
|
4723
|
+
*/
|
|
4724
|
+
contextId?: string;
|
|
4725
|
+
/**
|
|
4726
|
+
* Type de contexte de recherche (actuellement vide)
|
|
4727
|
+
*/
|
|
4728
|
+
contextType?: "projects" | "organizations";
|
|
4729
|
+
/**
|
|
4730
|
+
* Slug du costume utilisé pour la recherche
|
|
4731
|
+
*/
|
|
4732
|
+
costumSlug?: string;
|
|
4733
|
+
/**
|
|
4734
|
+
* Clés de source pour la recherche
|
|
4735
|
+
*/
|
|
4736
|
+
sourceKey?: string[];
|
|
4737
|
+
/**
|
|
4738
|
+
* Indique si le mode d'édition du costume est activé (toujours désactivé)
|
|
4739
|
+
*/
|
|
4740
|
+
costumEditMode?: boolean;
|
|
4741
|
+
options?: {
|
|
4742
|
+
tags?: {
|
|
4743
|
+
/**
|
|
4744
|
+
* Verbe d'action pour le filtre de recherche
|
|
4745
|
+
*/
|
|
4746
|
+
verb?: string;
|
|
4747
|
+
[k: string]: unknown;
|
|
4748
|
+
};
|
|
4749
|
+
[k: string]: unknown;
|
|
4750
|
+
};
|
|
4751
|
+
[k: string]: unknown;
|
|
4752
|
+
}
|
|
4753
|
+
|
|
4754
|
+
|
|
4755
|
+
export interface CoformAnswersByIdData {
|
|
4756
|
+
/**
|
|
4757
|
+
* ID de la réponse à récupérer
|
|
4758
|
+
*/
|
|
4759
|
+
answerId: string;
|
|
4760
|
+
/**
|
|
4761
|
+
* Chemin du finder utilisé pour la recherche (actuellement vide)
|
|
4762
|
+
*/
|
|
4763
|
+
finderPath?: string;
|
|
4764
|
+
/**
|
|
4765
|
+
* Liste des champs à retourner
|
|
4766
|
+
*/
|
|
4767
|
+
fields?: string[];
|
|
4768
|
+
[k: string]: unknown;
|
|
4769
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// TypeScript native types
|
|
2
2
|
import type { CollectionType } from "../types/entities.js";
|
|
3
3
|
|
|
4
|
-
export type EntityTag = "User" | "Organization" | "Project" | "Event" | "Poi" | "Badge" | "News" | "Comment";
|
|
4
|
+
export type EntityTag = "User" | "Organization" | "Project" | "Event" | "Poi" | "Badge" | "News" | "Comment" | "Answer";
|
|
5
5
|
export type CollectionKey = CollectionType; // Alias pour compatibilité
|
|
6
6
|
type BaseEntity = import("./BaseEntity.js").BaseEntity<any>;
|
|
7
7
|
type ApiClient = import("../ApiClient.js").default;
|
|
@@ -86,6 +86,7 @@ function _getEntityMeta(entityType: CollectionKey, __entityTag: EntityTag): Enti
|
|
|
86
86
|
Badge: selfTag === "Badge" ? selfClass : EntityRegistry.get("Badge"),
|
|
87
87
|
News: selfTag === "News" ? selfClass : EntityRegistry.get("News"),
|
|
88
88
|
Comment: selfTag === "Comment" ? selfClass : EntityRegistry.get("Comment"),
|
|
89
|
+
Answer: selfTag === "Answer" ? selfClass : EntityRegistry.get("Answer"),
|
|
89
90
|
};
|
|
90
91
|
|
|
91
92
|
const map: Record<CollectionKey, EntityMeta> = {
|
|
@@ -101,7 +102,8 @@ function _getEntityMeta(entityType: CollectionKey, __entityTag: EntityTag): Enti
|
|
|
101
102
|
Organization: commonDeps.Organization,
|
|
102
103
|
Project: commonDeps.Project
|
|
103
104
|
} },
|
|
104
|
-
comments: { entityClass: commonDeps.Comment as EntityClass, deps: { ...commonDeps } }
|
|
105
|
+
comments: { entityClass: commonDeps.Comment as EntityClass, deps: { ...commonDeps } },
|
|
106
|
+
answers: { entityClass: commonDeps.Answer as EntityClass, deps: { ...commonDeps } },
|
|
105
107
|
};
|
|
106
108
|
|
|
107
109
|
return map[entityType] || null;
|
|
@@ -148,6 +150,10 @@ export function createFromCollection(collection: CollectionKey, parent: ApiClien
|
|
|
148
150
|
comments: {
|
|
149
151
|
entityTag: "Comment",
|
|
150
152
|
meta: tag => _buildMeta(tag, { remove: [] })
|
|
153
|
+
},
|
|
154
|
+
answers: {
|
|
155
|
+
entityTag: "Answer",
|
|
156
|
+
meta: tag => _buildMeta(tag, { remove: [] })
|
|
151
157
|
}
|
|
152
158
|
};
|
|
153
159
|
const entry = _collectionMap[collection];
|
|
@@ -179,6 +185,7 @@ function _buildMeta(tag: EntityTag, options: { remove: string[] }): EntityMeta {
|
|
|
179
185
|
Badge: EntityRegistry.get("Badge"),
|
|
180
186
|
News: EntityRegistry.get("News"),
|
|
181
187
|
Comment: EntityRegistry.get("Comment"),
|
|
188
|
+
Answer: EntityRegistry.get("Answer")
|
|
182
189
|
};
|
|
183
190
|
// inject self
|
|
184
191
|
(allDeps as any)[tag] = EntityClass;
|
|
@@ -190,7 +197,7 @@ function _buildMeta(tag: EntityTag, options: { remove: string[] }): EntityMeta {
|
|
|
190
197
|
/**
|
|
191
198
|
* Cas spécifique des badges : seules certaines dépendances.
|
|
192
199
|
*/
|
|
193
|
-
function _buildCustomMeta(tag: "Badge"): EntityMeta {
|
|
200
|
+
function _buildCustomMeta(tag: "Badge" | "Answer"): EntityMeta {
|
|
194
201
|
const EntityClass = EntityRegistry.get(tag) as EntityClass;
|
|
195
202
|
const deps: EntityDeps = {
|
|
196
203
|
EndpointApi: EntityRegistry.get("EndpointApi"),
|
package/src/api/News.ts
CHANGED
|
@@ -91,10 +91,8 @@ export class News extends BaseEntity<NewsItemNormalized> {
|
|
|
91
91
|
if (!this.id) throw new ApiError("Impossible de rafraîchir sans ID.", 400);
|
|
92
92
|
const id = this.id; // Type narrowing
|
|
93
93
|
|
|
94
|
-
const newsArray = await this.
|
|
95
|
-
|
|
96
|
-
);
|
|
97
|
-
|
|
94
|
+
const newsArray = await this.endpointApi.getNewsById({ ids: [id] });
|
|
95
|
+
|
|
98
96
|
if (newsArray && Array.isArray(newsArray) && newsArray.length === 1) {
|
|
99
97
|
const data = newsArray[0];
|
|
100
98
|
this._setData(data, { forceInitialDraftReset: true });
|
package/src/api/Organization.ts
CHANGED
|
@@ -7,9 +7,9 @@ import type {
|
|
|
7
7
|
GetMembersAdminData,
|
|
8
8
|
GetMembersNoAdminData
|
|
9
9
|
} from "./EndpointApi.types.js";
|
|
10
|
+
import type { OrganizationItemNormalized } from "./serverDataType/Organization.js";
|
|
10
11
|
import type { User } from "./User.js";
|
|
11
12
|
|
|
12
|
-
type OrganizationItemNormalized = import("./serverDataType/Organization.js").OrganizationItemNormalized;
|
|
13
13
|
|
|
14
14
|
export class Organization extends BaseEntity<OrganizationItemNormalized> {
|
|
15
15
|
static override entityType = "organizations";
|
|
@@ -430,4 +430,13 @@ export class Organization extends BaseEntity<OrganizationItemNormalized> {
|
|
|
430
430
|
return super.searchCostum(data);
|
|
431
431
|
}
|
|
432
432
|
|
|
433
|
+
/**
|
|
434
|
+
* {@inheritDoc BaseEntity#coformAnswersSearch}
|
|
435
|
+
*
|
|
436
|
+
* Cette méthode est redéfinie ici pour fournir des types spécifiques à l'entité Answer.
|
|
437
|
+
*/
|
|
438
|
+
override async coformAnswersSearch(data: Parameters<BaseEntity<OrganizationItemNormalized>["coformAnswersSearch"]>[0]) {
|
|
439
|
+
return super.coformAnswersSearch(data);
|
|
440
|
+
}
|
|
441
|
+
|
|
433
442
|
}
|
package/src/api/User.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ApiError } from "../error.js";
|
|
1
|
+
import { ApiError, ApiResponseError } from "../error.js";
|
|
2
2
|
import { BaseEntity } from "./BaseEntity.js";
|
|
3
|
+
import { createFromCollection } from "./EntityRegistry.js";
|
|
3
4
|
import { UserMixin } from "../mixin/UserMixin.js";
|
|
4
5
|
|
|
5
6
|
import type { Badge } from "./Badge.js";
|
|
@@ -18,6 +19,8 @@ import type {
|
|
|
18
19
|
GetFriendsAdminData
|
|
19
20
|
} from "./EndpointApi.types.js";
|
|
20
21
|
import type { Organization } from "./Organization.js";
|
|
22
|
+
import type { GetElementsKeyResponse } from "@/types/api-responses.js";
|
|
23
|
+
import type { EntityTypes } from "@/types/entities.js";
|
|
21
24
|
|
|
22
25
|
type ApiClient = import("../ApiClient.js").default;
|
|
23
26
|
type UserItemNormalized = import("./serverDataType/User.js").UserItemNormalized;
|
|
@@ -861,6 +864,44 @@ export class User extends BaseEntity<UserItemNormalized> {
|
|
|
861
864
|
this._assertEntityType("citoyens");
|
|
862
865
|
return this._isLinked("follows");
|
|
863
866
|
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Retourne une entité à partir d'un slug.
|
|
870
|
+
*/
|
|
871
|
+
async entitySlug(slug: string): Promise<EntityTypes> {
|
|
872
|
+
if(!this.isMe){
|
|
873
|
+
throw new ApiError("Vous devez être connecté et être l'utilisateur pour créer cet entité.", 401);
|
|
874
|
+
}
|
|
875
|
+
if (!slug) {
|
|
876
|
+
throw new ApiError("slug requis", 400);
|
|
877
|
+
}
|
|
878
|
+
try {
|
|
879
|
+
const data = await this.endpointApi.getElementsKey({
|
|
880
|
+
pathParams:{
|
|
881
|
+
slug: slug
|
|
882
|
+
}
|
|
883
|
+
}) as GetElementsKeyResponse;
|
|
884
|
+
|
|
885
|
+
if(data.contextId && data.contextType) {
|
|
886
|
+
const entity = createFromCollection(data.contextType, this, { id: data.contextId });
|
|
887
|
+
if (!entity) {
|
|
888
|
+
throw new ApiResponseError(`Le type d'entité pour le slug ${slug} n'est pas reconnu`, 200, data as object);
|
|
889
|
+
}
|
|
890
|
+
await entity.get();
|
|
891
|
+
// On sait que c'est l'un des types concrets → on caste
|
|
892
|
+
return entity as EntityTypes;
|
|
893
|
+
} else {
|
|
894
|
+
throw new ApiResponseError(`Le slug ${slug} n'est pas valide`, 200, data as object);
|
|
895
|
+
}
|
|
896
|
+
} catch (error) {
|
|
897
|
+
if(error instanceof ApiResponseError) {
|
|
898
|
+
throw new ApiResponseError(`Impossible de récupérer l'identifiant pour le slug ${slug}`, error.status, error.responseData);
|
|
899
|
+
} else {
|
|
900
|
+
throw error;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
}
|
|
864
905
|
}
|
|
865
906
|
|
|
866
907
|
// Incorporation des mixins dans User
|