@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@communecter/cocolight-api-client",
3
- "version": "1.0.56",
3
+ "version": "1.0.58",
4
4
  "description": "Client Axios simplifié pour l'API cocolight",
5
5
  "repository": {
6
6
  "type": "git",
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
+ }
@@ -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
 
@@ -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.callIsConnected(() =>
95
- this.endpointApi.getNewsById({ ids: [id] })
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 });
@@ -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