@communecter/cocolight-api-client 1.0.132 → 1.0.134

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.
@@ -41,6 +41,9 @@ type ActionInput = {
41
41
  type FormInput = {
42
42
  id: string;
43
43
  } | Record<string, any>;
44
+ type AnswerInput = {
45
+ id: string;
46
+ } | Record<string, any>;
44
47
  type ApiClient = import("../ApiClient.js").default;
45
48
  type EndpointApi = import("./EndpointApi.js").default;
46
49
  type User = import("./User.js").User;
@@ -108,6 +111,7 @@ interface EntityTypeMap {
108
111
  type ReadableWithMeta = import("stream").Readable & {
109
112
  path?: string;
110
113
  mimeType?: string;
114
+ size?: number;
111
115
  };
112
116
  type UploadInput = File | Blob | Buffer | import("stream").Readable;
113
117
  type ValidatedUpload = File | Buffer | ReadableWithMeta;
@@ -527,6 +531,37 @@ export declare class BaseEntity<TServerData = any> {
527
531
  * @private
528
532
  */
529
533
  protected _validateFile(fileInput: UploadInput): Promise<ValidatedUpload>;
534
+ /**
535
+ * Prépare un fichier pour un upload multipart **sans restriction MIME**.
536
+ *
537
+ * Diffère de `_validateImage` / `_validateFile` (liste MIME blanche stricte) :
538
+ * accepte tout MIME et garantit la conversion `Buffer → annotated stream` en
539
+ * Node (le multipart encoder du package `form-data` ignore les Buffer bruts ;
540
+ * il a besoin de `path` + `mimeType` sur un Readable).
541
+ *
542
+ * Pensé pour les endpoints d'upload large-spectre (ex: coform où l'utilisateur
543
+ * peut uploader PNG, GIF, WebP, PDF, DOCX, XLSX, etc. — c'est le backend qui
544
+ * filtre selon la config du Form, pas le client).
545
+ *
546
+ * Compatible browser + Node :
547
+ * - Browser `File` → pass-through
548
+ * - Browser `Blob` → wrap en `File` (génère nom + extension via MIME)
549
+ * - Node `Buffer` → détecte MIME via `file-type`, convertit en `Readable`
550
+ * annoté (`path`, `mimeType`)
551
+ * - Node `Readable` → pass-through si annoté, sinon utilise `fallbackName`
552
+ *
553
+ * @param input - Fichier à uploader (Buffer/File/Blob/Readable)
554
+ * @param fallbackName - Nom à utiliser si l'input n'en porte pas. Défaut `upload-<ts>`.
555
+ * @returns `{ qqfile, qqfilename, qqtotalfilesize }` prêt pour multipart.
556
+ * @throws {ApiError} si le type de l'input n'est pas reconnu.
557
+ *
558
+ * @protected
559
+ */
560
+ protected _prepareUploadFile(input: UploadInput, fallbackName?: string): Promise<{
561
+ qqfile: ValidatedUpload;
562
+ qqfilename: string;
563
+ qqtotalfilesize: number;
564
+ }>;
530
565
  /**
531
566
  * Valide les entrées d'upload de fichiers.
532
567
  *
@@ -539,14 +574,17 @@ export declare class BaseEntity<TServerData = any> {
539
574
  */
540
575
  private _validateUploadInput;
541
576
  /**
542
- * Transforme un Buffer en ReadableStream équivalent à fs.createReadStream
577
+ * Transforme un Buffer en ReadableStream équivalent à fs.createReadStream.
578
+ *
579
+ * Note : passé `protected` car réutilisé par `_prepareUploadFile()` (Answer).
580
+ *
543
581
  * @param buffer - Le buffer contenant les données binaires
544
582
  * @param [filename="file.bin"] - Nom de fichier (utilisé dans FormData)
545
583
  * @param [mimeType="application/octet-stream"] - Type MIME (utilisé dans FormData)
546
584
  * @returns - Readable doté de `path` et `mimeType`
547
- * @private
585
+ * @protected
548
586
  */
549
- private _createReadStreamFromBuffer;
587
+ protected _createReadStreamFromBuffer(buffer: Buffer, filename?: string, mimeType?: string): Promise<ReadableWithMeta>;
550
588
  /**
551
589
  * Transforme un Buffer en ReadableStream.
552
590
  *
@@ -1195,6 +1233,21 @@ export declare class BaseEntity<TServerData = any> {
1195
1233
  * const answers = await form.getAnswers(); // utilise le costumContext de l'org
1196
1234
  */
1197
1235
  form(formData?: FormInput): Promise<Form>;
1236
+ /**
1237
+ * Crée une instance d'Answer rattachée à l'entité courante.
1238
+ *
1239
+ * Méthode autorisée uniquement sur `Form` (la seule entité qui porte un
1240
+ * `id` de formulaire pré-rempli pour les drafts). Les autres entités la
1241
+ * bloquent via cet override par défaut qui throw.
1242
+ *
1243
+ * Pour fetch une Answer existante sans contexte Form, passer par
1244
+ * `EntityRegistry.createEntityFromData` ou un endpoint adhoc.
1245
+ *
1246
+ * @param _answerData - `{ id: string }` (fetch) ou objet partiel (draft).
1247
+ * @returns Une Answer.
1248
+ * @throws {ApiError} 501 sur les entités non supportées.
1249
+ */
1250
+ answer(_answerData?: AnswerInput): Promise<Answer>;
1198
1251
  /**
1199
1252
  * Récupérer les organisations d'une entitée : la liste des organisations dont l'entité est membre ou admin valide.
1200
1253
  * Constant : GET_ORGANIZATIONS_ADMIN | GET_ORGANIZATIONS_NO_ADMIN
@@ -54,4 +54,28 @@ export declare class Form extends BaseEntity<FormItemNormalized> {
54
54
  getAnswers(data?: Partial<CoformAnswersSearchData>, options?: {
55
55
  restoredState?: PaginatorState;
56
56
  }): Promise<PaginatorPage<Answer>>;
57
+ /**
58
+ * {@inheritDoc BaseEntity#answer}
59
+ *
60
+ * Crée une instance d'Answer **rattachée à ce Form**.
61
+ *
62
+ * - Si `answerData.id` est fourni → fetch l'Answer existante (via `COFORM_ANSWERS_BY_ID`).
63
+ * - Sinon → crée un draft d'Answer avec `form: this.id` pré-rempli, prêt à
64
+ * être complété puis sauvegardé.
65
+ *
66
+ * Le parent de l'Answer renvoyée est ce Form — la chaîne `org > form > answer`
67
+ * est donc préservée, ce qui permet (à terme) à l'Answer de remonter le
68
+ * costumContext via `this.parent.parent` si besoin.
69
+ *
70
+ * @example
71
+ * // Fetch d'une Answer existante
72
+ * const form = await org.form({ id: "6925e2b05dd63b02ca70d6d9" });
73
+ * const answer = await form.answer({ id: "6925869ad76aaf6c5a2b2f8a" });
74
+ *
75
+ * // Création d'un draft
76
+ * const draft = await form.answer();
77
+ * draft.data.answers = { "field1": "value1" };
78
+ * await draft.save();
79
+ */
80
+ answer(answerData?: Parameters<BaseEntity<FormItemNormalized>["answer"]>[0]): Promise<Answer>;
57
81
  }
@@ -149,11 +149,6 @@ export declare class Project extends BaseEntity<ProjectItemNormalized> {
149
149
  * Crée une instance de badge et la récupère si nécessaire.
150
150
  */
151
151
  badge(badgeData?: Parameters<BaseEntity<ProjectItemNormalized>["badge"]>[0]): Promise<import("./Badge.js").Badge>;
152
- /**
153
- * {@inheritDoc BaseEntity#news}
154
- *
155
- * Crée une instance de news et la récupère si nécessaire.
156
- */
157
152
  /**
158
153
  * {@inheritDoc BaseEntity#form}
159
154
  *
@@ -162,6 +157,11 @@ export declare class Project extends BaseEntity<ProjectItemNormalized> {
162
157
  * `coformAnswersSearch` avec le bon costumContext.
163
158
  */
164
159
  form(formData?: Parameters<BaseEntity<ProjectItemNormalized>["form"]>[0]): Promise<import("./Form.js").Form>;
160
+ /**
161
+ * {@inheritDoc BaseEntity#news}
162
+ *
163
+ * Crée une instance de news et la récupère si nécessaire.
164
+ */
165
165
  news(newsData?: Parameters<BaseEntity<ProjectItemNormalized>["news"]>[0]): Promise<import("./News.js").News>;
166
166
  /**
167
167
  * Vérifie qu'un milestoneId existe dans `serverData.oceco.milestones[]`.
@@ -55,6 +55,12 @@ export interface AnswerItemJson {
55
55
  project?: AnswerProjectRef;
56
56
  [key: string]: unknown;
57
57
  }
58
+ /**
59
+ * Raisons de refus d'édition côté backend, calculées par `coformAnswersById`
60
+ * et présentes dans la réponse normalisée. Utilisé par les UI pour distinguer
61
+ * les modes readonly/edit et afficher des messages contextuels.
62
+ */
63
+ export type AnswerEditDeniedReason = "not_logged_in" | "not_owner" | "form_inactive" | "form_closed";
58
64
  export interface AnswerItemNormalized {
59
65
  id: string;
60
66
  _id: ObjectID;
@@ -64,6 +70,7 @@ export interface AnswerItemNormalized {
64
70
  user?: string | User;
65
71
  links?: AnswerLinksBlock;
66
72
  draft?: boolean;
73
+ finished?: boolean;
67
74
  answers?: Record<string, unknown>;
68
75
  context?: ParentsMap | Record<string, Organization | Project>;
69
76
  form?: string;
@@ -74,6 +81,13 @@ export interface AnswerItemNormalized {
74
81
  date: Date;
75
82
  }>;
76
83
  project?: AnswerProjectRef;
84
+ /**
85
+ * L'utilisateur courant peut-il éditer cette réponse ? Calculé côté backend.
86
+ * Présent par défaut, ou enrichi avec le contexte si `formId` est fourni.
87
+ */
88
+ canEdit?: boolean;
89
+ /** Raison si `canEdit === false`. `null` si `canEdit === true`. */
90
+ editDeniedReason?: AnswerEditDeniedReason | null;
77
91
  [key: string]: unknown;
78
92
  }
79
93
  export {};