@communecter/cocolight-api-client 1.0.137 → 1.0.138

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.137",
3
+ "version": "1.0.138",
4
4
  "description": "Client Axios simplifié pour l'API cocolight",
5
5
  "repository": {
6
6
  "type": "git",
package/src/api/Action.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ApiError } from "../error.js";
2
2
  import { BaseEntity } from "./BaseEntity.js";
3
3
 
4
- import type { CostumProjectActionRequestNewData } from "./EndpointApi.types.js";
4
+ import type { CostumProjectActionRequestNewData, DeleteElementData } from "./EndpointApi.types.js";
5
5
  import type { ActionItemNormalized } from "./serverDataType/Action.js";
6
6
 
7
7
  /**
@@ -552,6 +552,68 @@ export class Action extends BaseEntity<ActionItemNormalized> {
552
552
  return result;
553
553
  }
554
554
 
555
+ /**
556
+ * Supprime définitivement cette Action via `DELETE_ELEMENT` (`type=actions`).
557
+ *
558
+ * **Guard** : autorisation client via `isAuthorOrAdmin({checkHierarchy: true})` :
559
+ * - **auteur** de l'Action (`serverData.creator === userId`), OU
560
+ * - **admin** du projet parent via la hiérarchie
561
+ * (`serverData.parent[projectId]` × `userContext.links.projects[projectId].isAdmin`).
562
+ *
563
+ * Le check exploite `_isAdminViaHierarchy` (étendu à `actions` côté BaseEntity)
564
+ * qui remonte vers le Project parent via `serverData.parent`.
565
+ *
566
+ * **Pré-requis** :
567
+ * - `userContext` (User connecté) doit avoir `serverData.links.projects` chargés
568
+ * (cas `api.me()`).
569
+ * - L'Action doit avoir `serverData.parent` populé (cas après `get()` ou
570
+ * `project.action({id})` qui fait un get automatique).
571
+ *
572
+ * Après succès :
573
+ * - `serverData` et `draftData` sont vidés (sans casser la réactivité)
574
+ * - `_isDeleted = true` → toute mutation ultérieure (`save`, `updateField`, etc.) throw
575
+ *
576
+ * @param reason - Raison libre transmise au backend (audit). Défaut : `"delete action"`.
577
+ * @throws {ApiError} 400 si l'Action n'a pas d'id (jamais sauvegardée).
578
+ * @throws {ApiError} 403 si ni auteur ni admin du projet parent.
579
+ *
580
+ * @example
581
+ * const action = await project.action({ id: actionId });
582
+ * await action.delete(); // OK si auteur OU admin projet
583
+ * action._isDeleted; // true
584
+ *
585
+ * @example
586
+ * // Raison custom (audit)
587
+ * await action.delete("Annulation suite à doublon (ticket #123)");
588
+ */
589
+ async delete(reason: string = "delete action"): Promise<void> {
590
+ if (!this.id) {
591
+ throw new ApiError("Vous devez fournir un id pour supprimer une Action.", 400);
592
+ }
593
+
594
+ // Guard : auteur OU admin du projet parent (via hiérarchie).
595
+ if (!this.isAuthorOrAdmin({ checkHierarchy: true })) {
596
+ throw new ApiError(
597
+ "Suppression refusée — vous devez être l'auteur de l'Action "
598
+ + "ou administrateur du projet parent.",
599
+ 403
600
+ );
601
+ }
602
+
603
+ const data: DeleteElementData = {
604
+ reason,
605
+ pathParams: { type: "actions", id: this.id },
606
+ };
607
+
608
+ await this.callIsConnected(() => this.endpointApi.deleteElement(data));
609
+
610
+ // Vider les objets réactifs sans casser la réactivité (pattern cf. Answer.delete / Comment.delete)
611
+ Object.keys(this._draftData).forEach(key => delete this._draftData[key]);
612
+ Object.keys(this._serverData).forEach(key => delete (this._serverData as any)[key]);
613
+
614
+ this._isDeleted = true;
615
+ }
616
+
555
617
  // ───────────────────────────────────────────────────────────────────────────
556
618
  // Privés
557
619
  // ───────────────────────────────────────────────────────────────────────────
@@ -2777,7 +2777,7 @@ export class BaseEntity<TServerData = any> {
2777
2777
  let hierarchyField: Record<string, any> | undefined;
2778
2778
  if (entityType === "events") {
2779
2779
  hierarchyField = entityData?.organizer;
2780
- } else if (entityType === "projects" || entityType === "poi" || entityType === "classifieds") {
2780
+ } else if (entityType === "projects" || entityType === "poi" || entityType === "classifieds" || entityType === "actions") {
2781
2781
  hierarchyField = entityData?.parent;
2782
2782
  } else {
2783
2783
  // Organizations et autres types n'ont pas de hiérarchie parent
@@ -281,6 +281,41 @@ export declare class Action extends BaseEntity<ActionItemNormalized> {
281
281
  * Effets : status=disabled + unset tracking.
282
282
  */
283
283
  archive(): Promise<unknown>;
284
+ /**
285
+ * Supprime définitivement cette Action via `DELETE_ELEMENT` (`type=actions`).
286
+ *
287
+ * **Guard** : autorisation client via `isAuthorOrAdmin({checkHierarchy: true})` :
288
+ * - **auteur** de l'Action (`serverData.creator === userId`), OU
289
+ * - **admin** du projet parent via la hiérarchie
290
+ * (`serverData.parent[projectId]` × `userContext.links.projects[projectId].isAdmin`).
291
+ *
292
+ * Le check exploite `_isAdminViaHierarchy` (étendu à `actions` côté BaseEntity)
293
+ * qui remonte vers le Project parent via `serverData.parent`.
294
+ *
295
+ * **Pré-requis** :
296
+ * - `userContext` (User connecté) doit avoir `serverData.links.projects` chargés
297
+ * (cas `api.me()`).
298
+ * - L'Action doit avoir `serverData.parent` populé (cas après `get()` ou
299
+ * `project.action({id})` qui fait un get automatique).
300
+ *
301
+ * Après succès :
302
+ * - `serverData` et `draftData` sont vidés (sans casser la réactivité)
303
+ * - `_isDeleted = true` → toute mutation ultérieure (`save`, `updateField`, etc.) throw
304
+ *
305
+ * @param reason - Raison libre transmise au backend (audit). Défaut : `"delete action"`.
306
+ * @throws {ApiError} 400 si l'Action n'a pas d'id (jamais sauvegardée).
307
+ * @throws {ApiError} 403 si ni auteur ni admin du projet parent.
308
+ *
309
+ * @example
310
+ * const action = await project.action({ id: actionId });
311
+ * await action.delete(); // OK si auteur OU admin projet
312
+ * action._isDeleted; // true
313
+ *
314
+ * @example
315
+ * // Raison custom (audit)
316
+ * await action.delete("Annulation suite à doublon (ticket #123)");
317
+ */
318
+ delete(reason?: string): Promise<void>;
284
319
  /**
285
320
  * Helper privé : délègue à `BaseEntity.updateField()` pour un path donné.
286
321
  * Bénéficie du normalize automatique (R0 Date → isoDate, R1 collapse setType,