@communecter/cocolight-api-client 1.0.179 → 1.0.181

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.179",
3
+ "version": "1.0.181",
4
4
  "description": "Client Axios simplifié pour l'API cocolight",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,5 @@
1
1
  import type ApiClient from "../ApiClient.js";
2
- import type { DocumentListData, PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GlobalAutocompleteAdminCostumData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, SearchEventsCostumData, ShareEventsData, InviteMembersData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, DeleteCoformAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, GenerateAnswerFromFormData, FundingEnvelopeData, CoremuOperationData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData, ImportPreviewData, ExportElementsData, ImportElementsData, GeocodageData, ValidateGroupData, SetSourceData, ModerateData, NewsModerateData, CommentModerateData, UploadDocumentData, ZoneGetShapeData, ZoneGetZonirisData, CostumListValuesData } from "./EndpointApi.types.js";
2
+ import type { DocumentListData, PersonRegisterData, AuthenticateUrlData, RefreshTokenUrlData, PasswordRecoveryData, PasswordResetData, ServerExchangeTokenData, ChangePasswordData, DeleteAccountData, UpdateSettingsData, UpdateBlockDescriptionData, UpdateBlockInfoData, UpdateBlockSocialData, UpdateBlockLocalityData, UpdateBlockSlugData, CheckData, ProfilImageData, ProfilBannerData, GetElementsAboutData, MulticonnectData, RelaunchInvitationData, GetNewsData, GetNewsByIdData, AddNewsData, AddImageNewsData, AddFileNewsData, DeleteNewsData, UpdateNewsData, ShareNewsData, GetCommentsData, AddCommentsData, DeleteCommentsData, UpdateCommentsData, SearchTagsData, ShowVoteData, GlobalAutocompleteData, CityAutocompleteData, CityAutocompleteByCountryData, SuggestionInputData, GetProjectsNoAdminData, GetProjectsAdminData, GetPoisNoAdminData, GetPoisAdminData, GlobalAutocompleteAdminCostumData, GetOrganizationsNoAdminData, GetOrganizationsAdminData, GetUserEligiblePlacesData, GetMembersNoAdminData, GetMembersAdminData, GetFriendsAdminData, GetSubscriptionsData, GetSubscriptionsAdminData, GetSubscribersData, GetSubscribersAdminData, GetContributorsNoAdminData, GetContributorsAdminData, GetBadgesData, GetBadgesFiltersData, ConnectData, CreateInvitationLinkData, ConnectByRefData, DisconnectData, GetElementsKeyData, GetFavorisData, DeleteFavorisData, AddFavorisData, AddOrganizationData, AddProjectData, AddPoiData, AddEventData, DeleteElementData, AddImageElementData, LinkValidateData, SearchMemberAutocompleteData, GetNotificationsData, GetNotificationsCountData, NotificationUpdateData, MarkNotificationAsReadData, ActivitypubSearchData, ActivitypubLinkData, ActivitypubGetCommunityData, GetBadgeData, AddBadgesData, AssignBadgesData, GetEventsData, SearchEventsCostumData, ShareEventsData, InviteMembersData, FollowData, GetCostumJsonData, GlobalAutocompleteCostumData, NavigatorGettlData, CostumEventRequestActorsData, CostumEventRequestSubeventsData, CostumEventRequestElementEventData, CostumEventRequestCategoriesData, CostumEventRequestDatesData, CostumEventRequestEventData, CostumEventRequestLinkTlToEventData, CostumEventRequestLoadContextTagData, GetGalleryData, GetAttendeesNoAdminData, GetAttendeesAdminData, CoformAnswersSearchData, CoformAnswersByIdData, GetCoformByIdData, CoformUploadAnswerFileData, DeleteCoformAnswerFileData, CoformGetAnswerFilesData, GetCoformCatalogsData, SaveCoformAnswerData, GetCoformAnswerHistoryData, GetCoformMultievalDataData, GetCoformCommontableContributorsData, AddVoteData, AddReportAbuseData, UpdatePathValueData, DeleteDocumentByContextData, DeleteDocumentByIdData, DemoteAdminData, CostumFilterCoformData, CostumFilterCoformByPathData, GetCountriesData, SearchZonesData, CoformAnswersByFormsData, GenerateAnswerFromFormData, FundingEnvelopeData, CoremuOperationData, CostumProjectActionRequestNewData, CostumProjectActionRequestSetStatusData, CostumProjectActionRequestSetDateData, CostumProjectActionRequestSetContributorsData, CostumProjectActionRequestCancelData, CostumProjectActionRequestArchiveData, LinkDiscourseAccountData, UnlinkDiscourseAccountData, DiscourseProfileData, DiscourseCheckEmailData, DiscourseDismissLinkData, LinkMediawikiAccountData, UnlinkMediawikiAccountData, GetMediawikiContributionsData, AddClassifiedData, PersonActivateData, ImportPreviewData, ExportElementsData, ImportElementsData, GeocodageData, ValidateGroupData, SetSourceData, ModerateData, NewsModerateData, CommentModerateData, UploadDocumentData, ZoneGetShapeData, ZoneGetZonirisData, CostumListValuesData, DirectoryProposalData, DirectoryProposalCountData, DirectoryProposalNewCounterData } from "./EndpointApi.types.js";
3
3
  /**
4
4
  * Classe EndpointApi générée automatiquement depuis endpoints-copie.json
5
5
  */
@@ -101,6 +101,15 @@ export declare class EndpointApi {
101
101
  * @throws {Error} - En cas d'erreur inattendue.
102
102
  */
103
103
  passwordRecovery(data: PasswordRecoveryData): Promise<any>;
104
+ /**
105
+ * Nouveau mot de passe via le lien de récupération : ÉTAPE 2 du flux « mot de passe oublié » : applique le nouveau mot de passe à partir du code reçu par email. L'ÉTAPE 1 est PASSWORD_RECOVERY (POST /co2/person/sendemail), qui pose le code et envoie le lien `/recover/<user>/<code>` — c'est ce lien qui amène ici. ⚠️ SANS ÉQUIVALENT LEGACY — divergence de mécanisme ASSUMÉE et plus sûre : le legacy PHP réinitialise le mot de passe AVANT toute preuve de possession de l'adresse et l'envoie EN CLAIR dans le mail (SendEmailAction.php:39-57), alors qu'ici seul le porteur du code reçu peut changer le mot de passe. Le code est à USAGE UNIQUE et expire (24 h) : la vérification et l'écriture se font dans une seule opération conditionnelle côté backend. Échecs (code faux / expiré / déjà consommé / mot de passe trop court) : HTTP 200 `{result:false, msg}` — le message ne distingue pas les cas (anti-énumération). Anti-brute-force : 10 essais / 10 min par compte visé, 30 / 10 min par IP.
106
+ * Constant : PASSWORD_RESET
107
+ * @param data - Données envoyées à l'API
108
+ * @returns Les données de réponse.
109
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
110
+ * @throws {Error} - En cas d'erreur inattendue.
111
+ */
112
+ passwordReset(data: PasswordResetData): Promise<any>;
104
113
  /**
105
114
  * Échange de token avec un autre serveur : Permet de se connecter à un autre serveur Communecter en échangeant un token.
106
115
  * Constant : SERVER_EXCHANGE_TOKEN
@@ -240,6 +249,16 @@ export declare class EndpointApi {
240
249
  * @throws {Error} - En cas d'erreur inattendue.
241
250
  */
242
251
  multiconnect(data: MulticonnectData): Promise<any>;
252
+ /**
253
+ * Relancer une invitation : Renvoie l'e-mail d'invitation à un compte encore en attente d'activation (roles.tobeactivated). Programme un mail 'relaunchInvitation' avec le lien d'activation. Garde : super-admin OU l'invitant du compte (invitedBy). ⚠ Le port NE reproduit PAS le legacy laxiste (qui répond toujours 200 text/html même en refus, sans garde d'accès réelle) : réponse JSON {result,msg}, garde réelle, anti-abus (3/10min par cible). Refus si le compte est déjà activé.
254
+ * Constant : RELAUNCH_INVITATION
255
+ * @param data - Données envoyées à l'API
256
+ * @returns Les données de réponse.
257
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
258
+ * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
259
+ * @throws {Error} - En cas d'erreur inattendue.
260
+ */
261
+ relaunchInvitation(data: RelaunchInvitationData): Promise<any>;
243
262
  /**
244
263
  * Récupérer les actualités : Récupère la liste d’actualités selon plusieurs critères.
245
264
  * Constant : GET_NEWS
@@ -602,6 +621,26 @@ export declare class EndpointApi {
602
621
  * @throws {Error} - En cas d'erreur inattendue.
603
622
  */
604
623
  connect(data: ConnectData): Promise<any>;
624
+ /**
625
+ * Générer un lien d'invitation partageable : Génère une URL d'invitation partageable /co2/link/connect/ref/<ref> vers un élément (organizations/projects/events). Tout citoyen connecté qui suit le lien rejoint l'élément IMMÉDIATEMENT (member, ou admin si isAdmin). L'appelant doit être ADMIN de la cible (ou super-admin). ⚠ Durcissements vs legacy : whitelist stricte des champs (pas de mass-assignment du body), ref cryptographique (le legacy dérivait uniqid()). Deux appels (isAdmin=true / false) alimentent costum.invitationLink / costum.invitationLinkAsMember côté UI.
626
+ * Constant : CREATE_INVITATION_LINK
627
+ * @param data - Données envoyées à l'API
628
+ * @returns Les données de réponse.
629
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
630
+ * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
631
+ * @throws {Error} - En cas d'erreur inattendue.
632
+ */
633
+ createInvitationLink(data: CreateInvitationLinkData): Promise<any>;
634
+ /**
635
+ * Rejoindre un élément par lien d'invitation : Consomme un lien d'invitation partageable (créé par CREATE_INVITATION_LINK). Le citoyen connecté est rattaché IMMÉDIATEMENT à l'élément cible (pas de toBeValidated), avec inviteByLink:true. Idempotent (déjà membre non-admin → no-op). Le legacy expose aussi un GET server-rendered pour les non-connectés (redirect + cookie) — non porté ; ici seule la branche connectée en JSON.
636
+ * Constant : CONNECT_BY_REF
637
+ * @param data - Données envoyées à l'API
638
+ * @returns Les données de réponse.
639
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
640
+ * @throws {ApiAuthenticationError} - En cas d'erreur d'authentification.
641
+ * @throws {Error} - En cas d'erreur inattendue.
642
+ */
643
+ connectByRef(data: ConnectByRefData): Promise<any>;
605
644
  /**
606
645
  * Se déconnecter d'un élément : Permet de supprimer le lien entre un utilisateur et un élément.
607
646
  * Constant : DISCONNECT
@@ -1539,5 +1578,32 @@ export declare class EndpointApi {
1539
1578
  * @throws {Error} - En cas d'erreur inattendue.
1540
1579
  */
1541
1580
  costumListValues(data: CostumListValuesData): Promise<any>;
1581
+ /**
1582
+ * Annuaire des communs (AAP) : Annuaire des communs AAP (port SDK de DirectoryProposalAction → Aap::globalAutocompleteProposal, citizenToolKit). Gates appliqués par le serveur : form.params.onlyAdminCanSeeList (restreint aux propres réponses + status='vote' sauf admin OU membre porteur de rôles dans les listes aapStep2.canEdit ET aapStep3.canEdit — bypass filters.formStandalone). MODE NORMAL (liste).
1583
+ * Constant : DIRECTORY_PROPOSAL
1584
+ * @param data - Données envoyées à l'API
1585
+ * @returns Les données de réponse.
1586
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
1587
+ * @throws {Error} - En cas d'erreur inattendue.
1588
+ */
1589
+ directoryProposal(data: DirectoryProposalData): Promise<any>;
1590
+ /**
1591
+ * Annuaire des communs (AAP) — compte seul : Annuaire des communs AAP (port SDK de DirectoryProposalAction → Aap::globalAutocompleteProposal, citizenToolKit). Gates appliqués par le serveur : form.params.onlyAdminCanSeeList (restreint aux propres réponses + status='vote' sauf admin OU membre porteur de rôles dans les listes aapStep2.canEdit ET aapStep3.canEdit — bypass filters.formStandalone). MODE COUNTONLY (compte sans résultats).
1592
+ * Constant : DIRECTORY_PROPOSAL_COUNT
1593
+ * @param data - Données envoyées à l'API
1594
+ * @returns Les données de réponse.
1595
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
1596
+ * @throws {Error} - En cas d'erreur inattendue.
1597
+ */
1598
+ directoryProposalCount(data: DirectoryProposalCountData): Promise<any>;
1599
+ /**
1600
+ * Annuaire des communs (AAP) — compteur de non-vus : Annuaire des communs AAP (port SDK de DirectoryProposalAction → Aap::globalAutocompleteProposal, citizenToolKit). Gates appliqués par le serveur : form.params.onlyAdminCanSeeList (restreint aux propres réponses + status='vote' sauf admin OU membre porteur de rôles dans les listes aapStep2.canEdit ET aapStep3.canEdit — bypass filters.formStandalone). MODE NEWCOUNTER (non-vus de l'utilisateur de session).
1601
+ * Constant : DIRECTORY_PROPOSAL_NEW_COUNTER
1602
+ * @param data - Données envoyées à l'API
1603
+ * @returns Les données de réponse.
1604
+ * @throws {ApiResponseError} - En cas d'erreur détectée dans la réponse.
1605
+ * @throws {Error} - En cas d'erreur inattendue.
1606
+ */
1607
+ directoryProposalNewCounter(data: DirectoryProposalNewCounterData): Promise<any>;
1542
1608
  }
1543
1609
  export default EndpointApi;
@@ -79,6 +79,21 @@ export interface PasswordRecoveryData {
79
79
  type: "password";
80
80
  [k: string]: unknown;
81
81
  }
82
+ export interface PasswordResetData {
83
+ /**
84
+ * Identifiant (_id) du compte, extrait du lien de récupération
85
+ */
86
+ user: string;
87
+ /**
88
+ * Code de récupération, extrait du lien (usage unique, expire au bout de 24 h)
89
+ */
90
+ code: string;
91
+ /**
92
+ * Nouveau mot de passe (8 caractères minimum — même règle que CHANGE_PASSWORD)
93
+ */
94
+ newPassword: string;
95
+ [k: string]: unknown;
96
+ }
82
97
  export interface ServerExchangeTokenData {
83
98
  /**
84
99
  * URL du serveur distant
@@ -494,6 +509,13 @@ export interface MulticonnectData {
494
509
  };
495
510
  [k: string]: unknown;
496
511
  }
512
+ export interface RelaunchInvitationData {
513
+ /**
514
+ * _id du compte invité à relancer
515
+ */
516
+ id: string;
517
+ [k: string]: unknown;
518
+ }
497
519
  export interface GetNewsData {
498
520
  /**
499
521
  * Limite de date timestamp ou 0
@@ -2737,6 +2759,39 @@ export interface ConnectData {
2737
2759
  connectType: "admin" | "member" | "contributor" | "attendee" | "friend" | "connect";
2738
2760
  [k: string]: unknown;
2739
2761
  }
2762
+ export interface CreateInvitationLinkData {
2763
+ /**
2764
+ * Type de l'élément cible
2765
+ */
2766
+ targetType: "organizations" | "projects" | "events";
2767
+ /**
2768
+ * _id de l'élément cible
2769
+ */
2770
+ targetId: string;
2771
+ /**
2772
+ * true → le lien confère le rôle admin ; défaut member
2773
+ */
2774
+ isAdmin?: boolean | string;
2775
+ /**
2776
+ * Rôles costum à poser sur le lien créé (optionnel)
2777
+ */
2778
+ roles?: unknown[] | string;
2779
+ /**
2780
+ * URL de redirection après rattachement (optionnel)
2781
+ */
2782
+ urlRedirection?: string;
2783
+ [k: string]: unknown;
2784
+ }
2785
+ export interface ConnectByRefData {
2786
+ pathParams?: {
2787
+ /**
2788
+ * Référence publique du lien (hex ; uniqid legacy 13 ou token Node 24) — segment d URL
2789
+ */
2790
+ ref: string;
2791
+ [k: string]: unknown;
2792
+ };
2793
+ [k: string]: unknown;
2794
+ }
2740
2795
  export interface DisconnectData {
2741
2796
  /**
2742
2797
  * ID de l'élément à déconnecter (projet, organisation...)
@@ -6687,3 +6742,207 @@ export interface CostumListValuesData {
6687
6742
  limit?: number;
6688
6743
  [k: string]: unknown;
6689
6744
  }
6745
+ export interface DirectoryProposalData {
6746
+ /**
6747
+ * searchType[0] = la COLLECTION interrogée par tous les find/count (typiquement 'answers'). Obligatoire — absent = 500 legacy.
6748
+ *
6749
+ * @minItems 1
6750
+ */
6751
+ searchType: [string, ...string[]];
6752
+ /**
6753
+ * Recherche texte (SearchNew::searchText) : $or par défaut name/title/slug/sigle/shortDescription + éclatement multi-mots.
6754
+ */
6755
+ name?: string;
6756
+ /**
6757
+ * Chemin de recherche texte SUPPLÉMENTAIRE — il S'AJOUTE au $or par défaut, il ne le remplace pas.
6758
+ */
6759
+ textPath?: string;
6760
+ /**
6761
+ * Tags — opérateur toujours $in ; chaque valeur devient une regex ANCRÉE insensible casse/accents (/^…$/i).
6762
+ */
6763
+ searchTags?: string[];
6764
+ /**
6765
+ * Chemin des tags (défaut serveur : 'tags').
6766
+ */
6767
+ tagsPath?: string;
6768
+ /**
6769
+ * Restreint à user = <userId>.
6770
+ */
6771
+ userId?: string;
6772
+ /**
6773
+ * Map {champ: 1|-1} (valeurs castées int) OU liste de champs (⇒ 1). Défaut serveur : {updated:-1}.
6774
+ */
6775
+ sortBy?: {
6776
+ [k: string]: 1 | -1;
6777
+ } | string[];
6778
+ /**
6779
+ * Projection Mongo (défaut : documents complets).
6780
+ */
6781
+ fields?: string[];
6782
+ /**
6783
+ * Offset (défaut serveur 0).
6784
+ */
6785
+ indexMin?: number;
6786
+ /**
6787
+ * Taille de page (défaut serveur 100) ; 'all' = SANS limite (findAndSort limit 0).
6788
+ */
6789
+ indexStep?: number | "all";
6790
+ /**
6791
+ * La PRÉSENCE de la clé ajoute count.<searchType[0]>. Transport form-urlencoded : count:false se sérialise "false" (truthy PHP) → identique à true ; const:true empêche le faux ami côté client.
6792
+ */
6793
+ count?: true;
6794
+ /**
6795
+ * Filtres. Clés à traitement SPÉCIAL (consommées, dans cet ordre) : formStandalone (bool, extrait en premier — bypass du gate onlyAdminCanSeeList) ; oneSubOrganization/allSubOrganisation (AVANT form, qu'ils REMPLACENT — voir plus bas) ; form (string → $or 3 voies : form=<val>, answers.aapStep2.choose.<idParentDuForm>.value='selected', links.aacForm.<formId> $exists — LE scoping réel de l'annuaire) ; address (string → regex accent-insensible sur <mapping.address>.postalCode/.name) ; views (['seen'|'notSeen'] → views.<userId SESSION> $exists — réponse USER-SCOPÉE : la query key doit porter l'userId) ; quartiers (string[] → answers.aapStep1.interventionArea $in) ; toute clé contenant '.choose.' (string[] → $in ; la valeur 'notselected' ajoute une branche $exists:false) ; admissibility (['admissible'|'inadmissible'] — [0] seul lu ; communauté CITOYENS du porteur ; 'admissible' = $ne 'inadmissible' donc matche aussi les non-notées ; ignoré si communauté vide) ; answers.aapStep1.depense.financer.idAndName ('<id>-idAndName-<nom>', [0] seul → $or name/id) ; vote (truthy → vote.<userId SESSION> $exists — user-scopé) ; inproject (['inproject'|'inproposal'] cumulables → project.id $exists true/false ; ⚠ supprime silencieusement un éventuel filters['project.id']) ; status (si le tableau contient 'unnotified' : status $ne notified/notificationSent ; la clé n'est retirée que si c'est la SEULE valeur, sinon le tableau ENTIER repart en pass-through). Sous-organisations (fix 2026-08 appliqué L+B, BUG-L-226/227) : oneSubOrganization PRIME (string[], valeurs éclatées sur '-' → form $in ; consomme aussi allSubOrganisation et form), sinon allSubOrganisation (string[] → form $in [valeurs + filters.form si présent]) — les deux REMPLACENT le scoping $or 3 voies de form. ⚠ Sur un serveur legacy ANTÉRIEUR au fix (branche fix/aap-suborganisation-filters) : oneSubOrganization était mort (pass-through → liste VIDE) et allSubOrganisation ajoutait null au $in en prod (élargit) / 500 en dev. Toute autre clé : pass-through SearchNew::searchFilters (tableau → $in de regex partielles ; string → $or [valeur, bool]).
6796
+ */
6797
+ filters?: {
6798
+ [k: string]: unknown;
6799
+ };
6800
+ pathParams?: {
6801
+ /**
6802
+ * Slug du costum (contexte). Le legacy accepte des appels sans source (purement contextuel via beforeAction) — le SDK le requiert : les usages site-json sont toujours sous costum.
6803
+ */
6804
+ source: string;
6805
+ /**
6806
+ * Id du FORM PARENT AAC. Effectivement requis (le legacy fait findOneById puis lit form.parent → 500 sans form valide). ⚠ Il ne filtre JAMAIS les résultats (scoping commenté, Aap.php:1201) : sans filters.form la requête balaie TOUTES les réponses de la collection — toujours poser filters.form.
6807
+ */
6808
+ form: string;
6809
+ [k: string]: unknown;
6810
+ };
6811
+ [k: string]: unknown;
6812
+ }
6813
+ export interface DirectoryProposalCountData {
6814
+ /**
6815
+ * searchType[0] = la COLLECTION interrogée par tous les find/count (typiquement 'answers'). Obligatoire — absent = 500 legacy.
6816
+ *
6817
+ * @minItems 1
6818
+ */
6819
+ searchType: [string, ...string[]];
6820
+ /**
6821
+ * Recherche texte (SearchNew::searchText) : $or par défaut name/title/slug/sigle/shortDescription + éclatement multi-mots.
6822
+ */
6823
+ name?: string;
6824
+ /**
6825
+ * Chemin de recherche texte SUPPLÉMENTAIRE — il S'AJOUTE au $or par défaut, il ne le remplace pas.
6826
+ */
6827
+ textPath?: string;
6828
+ /**
6829
+ * Tags — opérateur toujours $in ; chaque valeur devient une regex ANCRÉE insensible casse/accents (/^…$/i).
6830
+ */
6831
+ searchTags?: string[];
6832
+ /**
6833
+ * Chemin des tags (défaut serveur : 'tags').
6834
+ */
6835
+ tagsPath?: string;
6836
+ /**
6837
+ * Restreint à user = <userId>.
6838
+ */
6839
+ userId?: string;
6840
+ /**
6841
+ * Map {champ: 1|-1} (valeurs castées int) OU liste de champs (⇒ 1). Défaut serveur : {updated:-1}.
6842
+ */
6843
+ sortBy?: {
6844
+ [k: string]: 1 | -1;
6845
+ } | string[];
6846
+ /**
6847
+ * Projection Mongo (défaut : documents complets).
6848
+ */
6849
+ fields?: string[];
6850
+ /**
6851
+ * Offset (défaut serveur 0).
6852
+ */
6853
+ indexMin?: number;
6854
+ /**
6855
+ * Taille de page (défaut serveur 100) ; 'all' = SANS limite (findAndSort limit 0).
6856
+ */
6857
+ indexStep?: number | "all";
6858
+ /**
6859
+ * La PRÉSENCE de la clé ajoute count.<searchType[0]>. Transport form-urlencoded : count:false se sérialise "false" (truthy PHP) → identique à true ; const:true empêche le faux ami côté client.
6860
+ */
6861
+ count?: true;
6862
+ /**
6863
+ * Filtres. Clés à traitement SPÉCIAL (consommées, dans cet ordre) : formStandalone (bool, extrait en premier — bypass du gate onlyAdminCanSeeList) ; oneSubOrganization/allSubOrganisation (AVANT form, qu'ils REMPLACENT — voir plus bas) ; form (string → $or 3 voies : form=<val>, answers.aapStep2.choose.<idParentDuForm>.value='selected', links.aacForm.<formId> $exists — LE scoping réel de l'annuaire) ; address (string → regex accent-insensible sur <mapping.address>.postalCode/.name) ; views (['seen'|'notSeen'] → views.<userId SESSION> $exists — réponse USER-SCOPÉE : la query key doit porter l'userId) ; quartiers (string[] → answers.aapStep1.interventionArea $in) ; toute clé contenant '.choose.' (string[] → $in ; la valeur 'notselected' ajoute une branche $exists:false) ; admissibility (['admissible'|'inadmissible'] — [0] seul lu ; communauté CITOYENS du porteur ; 'admissible' = $ne 'inadmissible' donc matche aussi les non-notées ; ignoré si communauté vide) ; answers.aapStep1.depense.financer.idAndName ('<id>-idAndName-<nom>', [0] seul → $or name/id) ; vote (truthy → vote.<userId SESSION> $exists — user-scopé) ; inproject (['inproject'|'inproposal'] cumulables → project.id $exists true/false ; ⚠ supprime silencieusement un éventuel filters['project.id']) ; status (si le tableau contient 'unnotified' : status $ne notified/notificationSent ; la clé n'est retirée que si c'est la SEULE valeur, sinon le tableau ENTIER repart en pass-through). Sous-organisations (fix 2026-08 appliqué L+B, BUG-L-226/227) : oneSubOrganization PRIME (string[], valeurs éclatées sur '-' → form $in ; consomme aussi allSubOrganisation et form), sinon allSubOrganisation (string[] → form $in [valeurs + filters.form si présent]) — les deux REMPLACENT le scoping $or 3 voies de form. ⚠ Sur un serveur legacy ANTÉRIEUR au fix (branche fix/aap-suborganisation-filters) : oneSubOrganization était mort (pass-through → liste VIDE) et allSubOrganisation ajoutait null au $in en prod (élargit) / 500 en dev. Toute autre clé : pass-through SearchNew::searchFilters (tableau → $in de regex partielles ; string → $or [valeur, bool]).
6864
+ */
6865
+ filters?: {
6866
+ [k: string]: unknown;
6867
+ };
6868
+ pathParams?: {
6869
+ /**
6870
+ * Slug du costum (contexte). Le legacy accepte des appels sans source (purement contextuel via beforeAction) — le SDK le requiert : les usages site-json sont toujours sous costum.
6871
+ */
6872
+ source: string;
6873
+ /**
6874
+ * Id du FORM PARENT AAC. Effectivement requis (le legacy fait findOneById puis lit form.parent → 500 sans form valide). ⚠ Il ne filtre JAMAIS les résultats (scoping commenté, Aap.php:1201) : sans filters.form la requête balaie TOUTES les réponses de la collection — toujours poser filters.form.
6875
+ */
6876
+ form: string;
6877
+ [k: string]: unknown;
6878
+ };
6879
+ [k: string]: unknown;
6880
+ }
6881
+ export interface DirectoryProposalNewCounterData {
6882
+ /**
6883
+ * searchType[0] = la COLLECTION interrogée par tous les find/count (typiquement 'answers'). Obligatoire — absent = 500 legacy.
6884
+ *
6885
+ * @minItems 1
6886
+ */
6887
+ searchType: [string, ...string[]];
6888
+ /**
6889
+ * Recherche texte (SearchNew::searchText) : $or par défaut name/title/slug/sigle/shortDescription + éclatement multi-mots.
6890
+ */
6891
+ name?: string;
6892
+ /**
6893
+ * Chemin de recherche texte SUPPLÉMENTAIRE — il S'AJOUTE au $or par défaut, il ne le remplace pas.
6894
+ */
6895
+ textPath?: string;
6896
+ /**
6897
+ * Tags — opérateur toujours $in ; chaque valeur devient une regex ANCRÉE insensible casse/accents (/^…$/i).
6898
+ */
6899
+ searchTags?: string[];
6900
+ /**
6901
+ * Chemin des tags (défaut serveur : 'tags').
6902
+ */
6903
+ tagsPath?: string;
6904
+ /**
6905
+ * Restreint à user = <userId>.
6906
+ */
6907
+ userId?: string;
6908
+ /**
6909
+ * Map {champ: 1|-1} (valeurs castées int) OU liste de champs (⇒ 1). Défaut serveur : {updated:-1}.
6910
+ */
6911
+ sortBy?: {
6912
+ [k: string]: 1 | -1;
6913
+ } | string[];
6914
+ /**
6915
+ * Projection Mongo (défaut : documents complets).
6916
+ */
6917
+ fields?: string[];
6918
+ /**
6919
+ * Offset (défaut serveur 0).
6920
+ */
6921
+ indexMin?: number;
6922
+ /**
6923
+ * Taille de page (défaut serveur 100) ; 'all' = SANS limite (findAndSort limit 0).
6924
+ */
6925
+ indexStep?: number | "all";
6926
+ /**
6927
+ * La PRÉSENCE de la clé ajoute count.<searchType[0]>. Transport form-urlencoded : count:false se sérialise "false" (truthy PHP) → identique à true ; const:true empêche le faux ami côté client.
6928
+ */
6929
+ count?: true;
6930
+ /**
6931
+ * Filtres. Clés à traitement SPÉCIAL (consommées, dans cet ordre) : formStandalone (bool, extrait en premier — bypass du gate onlyAdminCanSeeList) ; oneSubOrganization/allSubOrganisation (AVANT form, qu'ils REMPLACENT — voir plus bas) ; form (string → $or 3 voies : form=<val>, answers.aapStep2.choose.<idParentDuForm>.value='selected', links.aacForm.<formId> $exists — LE scoping réel de l'annuaire) ; address (string → regex accent-insensible sur <mapping.address>.postalCode/.name) ; views (['seen'|'notSeen'] → views.<userId SESSION> $exists — réponse USER-SCOPÉE : la query key doit porter l'userId) ; quartiers (string[] → answers.aapStep1.interventionArea $in) ; toute clé contenant '.choose.' (string[] → $in ; la valeur 'notselected' ajoute une branche $exists:false) ; admissibility (['admissible'|'inadmissible'] — [0] seul lu ; communauté CITOYENS du porteur ; 'admissible' = $ne 'inadmissible' donc matche aussi les non-notées ; ignoré si communauté vide) ; answers.aapStep1.depense.financer.idAndName ('<id>-idAndName-<nom>', [0] seul → $or name/id) ; vote (truthy → vote.<userId SESSION> $exists — user-scopé) ; inproject (['inproject'|'inproposal'] cumulables → project.id $exists true/false ; ⚠ supprime silencieusement un éventuel filters['project.id']) ; status (si le tableau contient 'unnotified' : status $ne notified/notificationSent ; la clé n'est retirée que si c'est la SEULE valeur, sinon le tableau ENTIER repart en pass-through). Sous-organisations (fix 2026-08 appliqué L+B, BUG-L-226/227) : oneSubOrganization PRIME (string[], valeurs éclatées sur '-' → form $in ; consomme aussi allSubOrganisation et form), sinon allSubOrganisation (string[] → form $in [valeurs + filters.form si présent]) — les deux REMPLACENT le scoping $or 3 voies de form. ⚠ Sur un serveur legacy ANTÉRIEUR au fix (branche fix/aap-suborganisation-filters) : oneSubOrganization était mort (pass-through → liste VIDE) et allSubOrganisation ajoutait null au $in en prod (élargit) / 500 en dev. Toute autre clé : pass-through SearchNew::searchFilters (tableau → $in de regex partielles ; string → $or [valeur, bool]).
6932
+ */
6933
+ filters?: {
6934
+ [k: string]: unknown;
6935
+ };
6936
+ pathParams?: {
6937
+ /**
6938
+ * Slug du costum (contexte). Le legacy accepte des appels sans source (purement contextuel via beforeAction) — le SDK le requiert : les usages site-json sont toujours sous costum.
6939
+ */
6940
+ source: string;
6941
+ /**
6942
+ * Id du FORM PARENT AAC. Effectivement requis (le legacy fait findOneById puis lit form.parent → 500 sans form valide). ⚠ Il ne filtre JAMAIS les résultats (scoping commenté, Aap.php:1201) : sans filters.form la requête balaie TOUTES les réponses de la collection — toujours poser filters.form.
6943
+ */
6944
+ form: string;
6945
+ [k: string]: unknown;
6946
+ };
6947
+ [k: string]: unknown;
6948
+ }
@@ -1,7 +1,7 @@
1
1
  import { BaseEntity } from "./BaseEntity.js";
2
2
  import type { Answer } from "./Answer.js";
3
3
  import type { PaginatorPage, PaginatorState } from "./BaseEntity.js";
4
- import type { CoformAnswersSearchData } from "./EndpointApi.types.js";
4
+ import type { CoformAnswersSearchData, DirectoryProposalCountData, DirectoryProposalData, DirectoryProposalNewCounterData } from "./EndpointApi.types.js";
5
5
  import type { CoformCommonTableContributor, FormItemNormalized } from "./serverDataType/Form.js";
6
6
  /**
7
7
  * Une entrée de catalogue commonTable (une criteria agrégée cross-réponses).
@@ -29,6 +29,41 @@ export interface CommonTableCatalogEntry {
29
29
  * (`getCatalogs` normalise les `[]` PHP — catalogues vides — en `{}`).
30
30
  */
31
31
  export type CommonTableCatalogs = Record<string, Record<string, CommonTableCatalogEntry>>;
32
+ /**
33
+ * Les 10 blocs latéraux batch-résolus de l'annuaire des communs AAP
34
+ * (directoryproposal). Chaque bloc VIDE se sérialise `[]` (array PHP vide),
35
+ * peuplé c'est une map keyée par id.
36
+ */
37
+ export interface DirectoryProposalSideBlocks {
38
+ users: Record<string, unknown> | unknown[];
39
+ usersStatus: Record<string, unknown> | unknown[];
40
+ sousOrga: Record<string, unknown> | unknown[];
41
+ checkSeen: Record<string, unknown> | unknown[];
42
+ allActions: Record<string, unknown> | unknown[];
43
+ allImages: Record<string, unknown> | unknown[];
44
+ allDocuments: Record<string, unknown> | unknown[];
45
+ elements: Record<string, unknown> | unknown[];
46
+ inputs: Record<string, unknown> | unknown[];
47
+ allNotSeenComments: Record<string, unknown> | unknown[];
48
+ }
49
+ /**
50
+ * Réponse de `form.getProposals` (mode normal). `results` : lignes
51
+ * PRÉ-FORMATÉES par le serveur (parsePropositionData : `name`, `image`
52
+ * toujours présent, `tags` ré-indexés, `funds` agrégés, `user_count`,
53
+ * `interrest_count`…), normalisées map→tableau par le client (id injecté).
54
+ * À consommer BRUT — pour un détail/action, reviver l'Answer par id
55
+ * (`form.answer({ id })`), jamais via `_linkEntities` (les lignes ne sont
56
+ * pas des documents answers complets).
57
+ */
58
+ export interface DirectoryProposalPage extends DirectoryProposalSideBlocks {
59
+ results: Array<Record<string, unknown>>;
60
+ /** Présent SEULEMENT si la clé `count` était posée dans la requête. */
61
+ count?: Record<string, number>;
62
+ }
63
+ /** Réponse de `form.countProposals` (mode countonly) : count sans results, blocs latéraux présents et vides. */
64
+ export interface DirectoryProposalCountPage extends DirectoryProposalSideBlocks {
65
+ count: Record<string, number>;
66
+ }
32
67
  export declare class Form extends BaseEntity<FormItemNormalized> {
33
68
  static entityType: string;
34
69
  static entityTag: string;
@@ -156,4 +191,50 @@ export declare class Form extends BaseEntity<FormItemNormalized> {
156
191
  getCatalogs(params: {
157
192
  inputKeys: string[];
158
193
  }): Promise<CommonTableCatalogs>;
194
+ /**
195
+ * Gardes communes des 3 wrappers directoryproposal + construction des
196
+ * pathParams `{source, form}` : `source` = slug du parent costum (le Form
197
+ * doit avoir été créé via `org.form({id})` / `project.form({id})`),
198
+ * `form` = id de ce Form (le form PARENT AAC).
199
+ */
200
+ private _proposalPathParams;
201
+ /**
202
+ * Annuaire des communs AAP (`co2/aap/directoryproposal`, mode normal).
203
+ *
204
+ * Wrapper de `endpointApi.directoryProposal` qui encapsule les invariants
205
+ * piégeux du legacy :
206
+ * - `pathParams.form` ne FILTRE JAMAIS les résultats → `filters.form = this.id`
207
+ * est TOUJOURS injecté (sans lui, la requête balaierait toutes les réponses
208
+ * de la collection) ;
209
+ * - `searchType: ["answers"]` par défaut (obligatoire côté serveur) ;
210
+ * - `source` = slug du parent costum, `form` = id de ce Form.
211
+ *
212
+ * Le retour est BRUT (lignes pré-formatées serveur) — voir
213
+ * {@link DirectoryProposalPage}. Pagination : passer `indexStep`/`indexMin` ;
214
+ * poser la clé `count` (ex. `count: true`) pour recevoir `count.answers`.
215
+ * ⚠ `filters.views`/`filters.vote` scopent la réponse à l'utilisateur de
216
+ * SESSION — toute query key de cache doit alors porter l'userId.
217
+ *
218
+ * @example
219
+ * const org = await api.organization({ slug: "coSindniSmarterre" });
220
+ * const form = await org.form({ id: AAC_FORM_ID });
221
+ * const page = await form.getProposals({ indexStep: 30, indexMin: 0, count: true });
222
+ * page.results; // lignes pré-formatées (name, image, tags, funds…)
223
+ * page.count?.answers; // total
224
+ */
225
+ getProposals(data?: Partial<DirectoryProposalData>): Promise<DirectoryProposalPage>;
226
+ /**
227
+ * Annuaire des communs AAP — compte seul (mode countonly).
228
+ * Mêmes gardes et injections que {@link Form#getProposals} ; la réponse porte
229
+ * `count.<searchType[0]>` SANS `results` (blocs latéraux présents, vides `[]`).
230
+ */
231
+ countProposals(data?: Partial<DirectoryProposalCountData>): Promise<DirectoryProposalCountPage>;
232
+ /**
233
+ * Annuaire des communs AAP — compteur de non-vus (mode newcounter).
234
+ * Réponse `{ newCounter: int }` seule ; compteur de l'utilisateur de SESSION
235
+ * (0 si non connecté) — query key de cache à scoper par userId.
236
+ */
237
+ getProposalsNewCounter(data?: Partial<DirectoryProposalNewCounterData>): Promise<{
238
+ newCounter: number;
239
+ }>;
159
240
  }