@ikatec/digisac-api-sdk 3.0.0 → 3.1.0

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.
@@ -1,13 +1,71 @@
1
1
  import type { Contact } from '../contacts/types';
2
- import type { Pipeline } from '../pipeline/types';
2
+ import type { Pipeline, PipelineStage, PipelineStageReason, PipelineStageStatus } from '../pipeline/types';
3
3
  import type { User } from '../users/types';
4
+ type NamedRef = {
5
+ id: string;
6
+ name: string;
7
+ };
8
+ /** One entry of the card history — written on create and on every stage/status/owner change. */
9
+ export type CardMovement = {
10
+ id: string;
11
+ cardId: string;
12
+ accountId: string;
13
+ /** The user who made the change (the requester), not the card owner. */
14
+ userId: string;
15
+ pipelineId: string;
16
+ fromPipelineId: string | null;
17
+ toPipelineId: string | null;
18
+ fromPipelineStageId: string | null;
19
+ toPipelineStageId: string | null;
20
+ fromStageStatusId: string | null;
21
+ toStageStatusId: string | null;
22
+ fromOwnerId: string | null;
23
+ toOwnerId: string | null;
24
+ createdAt: string;
25
+ user?: NamedRef | null;
26
+ from_pipeline?: NamedRef | null;
27
+ to_pipeline?: NamedRef | null;
28
+ from_pipeline_stage?: NamedRef | null;
29
+ to_pipeline_stage?: NamedRef | null;
30
+ from_stage_status?: NamedRef | null;
31
+ to_stage_status?: NamedRef | null;
32
+ from_owner?: NamedRef | null;
33
+ to_owner?: NamedRef | null;
34
+ };
35
+ export type CardProduct = {
36
+ id: string;
37
+ cardId: string;
38
+ name: string;
39
+ /** Quantity (the backend column is spelled `ammount`). */
40
+ ammount: number;
41
+ value: number;
42
+ createdAt: string;
43
+ updatedAt: string;
44
+ };
45
+ export type CardComment = {
46
+ id: string;
47
+ cardId: string;
48
+ userId: string | null;
49
+ comment: string | null;
50
+ createdAt: string;
51
+ updatedAt: string;
52
+ user?: User | null;
53
+ files?: Record<string, unknown>[];
54
+ };
55
+ /**
56
+ * A sales funnel card (opportunity).
57
+ *
58
+ * `create` and `updateById` answer the raw entity (with `updatedAt`/`archivedAt`). `getMany` and
59
+ * `getById` go through the backend transformer: no `updatedAt`/`archivedAt`, plus `url`,
60
+ * `lastMessage` and `totalValue`; `getById` also joins the relationships below.
61
+ */
4
62
  export type Card = {
5
63
  id: string;
6
64
  title: string;
7
65
  description: string | null;
66
+ /** Position in the stage — set by the backend to the number of cards already in it. */
8
67
  order: number | null;
9
68
  isArchived: boolean;
10
- archivedAt: string | null;
11
69
  success: boolean | null;
12
70
  finishedAt: string | null;
13
71
  organization: string | null;
@@ -22,38 +80,62 @@ export type Card = {
22
80
  reasonId: string | null;
23
81
  ownerId: string | null;
24
82
  createdAt: string;
25
- updatedAt: string;
83
+ /** Only on create/update answers. */
84
+ updatedAt?: string;
85
+ /** Only on create/update answers. */
86
+ archivedAt?: string | null;
87
+ /** Only on getMany/getById answers (contact avatar URL, or empty string). */
88
+ url?: unknown;
89
+ /** Only on getMany/getById answers (contact last message, or empty string). */
90
+ lastMessage?: unknown;
91
+ /** Only on getMany/getById answers: sum of the products (`ammount * value`). */
92
+ totalValue?: number;
26
93
  contact?: Contact | null;
27
94
  owner?: User | null;
28
95
  pipeline?: Pipeline;
96
+ pipeline_stage?: PipelineStage | null;
97
+ stage_status?: PipelineStageStatus | null;
98
+ stage_reason?: PipelineStageReason | null;
99
+ movements?: CardMovement[];
100
+ products?: CardProduct[];
101
+ comments?: CardComment[];
29
102
  };
30
- export type CardRelationships = 'contact' | 'owner' | 'pipeline';
103
+ export type CardRelationships = 'contact' | 'owner' | 'pipeline' | 'pipeline_stage' | 'stage_status' | 'stage_reason' | 'movements' | 'products' | 'comments';
31
104
  export type CreateCardPayload = {
105
+ /** Up to 255 characters. */
32
106
  title: string;
33
107
  pipelineId: string;
34
- contactId?: string;
35
- pipelineStageId?: string;
108
+ contactId: string;
109
+ /** Must be a stage of `pipelineId`. */
110
+ pipelineStageId: string;
36
111
  description?: string;
112
+ ownerId?: string;
113
+ statusId?: string;
114
+ reasonId?: string;
37
115
  organization?: string;
38
116
  organizationSegment?: string;
39
117
  originChannel?: string;
40
118
  originCampaign?: string;
41
- ownerId?: string;
42
119
  };
43
120
  export type UpdateCardPayload = {
44
121
  title?: string;
45
122
  description?: string | null;
46
123
  contactId?: string | null;
124
+ /** Moves the card to another pipeline (send the target `pipelineStageId` along). */
125
+ pipelineId?: string;
47
126
  pipelineStageId?: string | null;
48
127
  statusId?: string | null;
49
128
  reasonId?: string | null;
50
129
  ownerId?: string | null;
130
+ order?: number;
51
131
  organization?: string | null;
52
132
  organizationSegment?: string | null;
53
133
  originChannel?: string | null;
54
134
  originCampaign?: string | null;
55
135
  isArchived?: boolean;
136
+ /** Marks the card as won (`true`) or lost (`false`); the backend fills `finishedAt`. */
56
137
  success?: boolean | null;
57
138
  finishedAt?: string | null;
58
139
  };
140
+ export {};
59
141
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/cards/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IAEjB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAA;AAEhE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/cards/types.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,46 @@
1
1
  import type { Department } from '../departments/types';
2
- export type Pipeline = {
2
+ export type PipelineStageStatus = {
3
+ id: string;
4
+ /** The default "Finalizados" stage carries `STATUS_WON` and `STATUS_LOOSE`. */
5
+ name: string;
6
+ position: number;
7
+ pipelineId: string;
8
+ stageId: string;
9
+ accountId: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ deletedAt: string | null;
13
+ };
14
+ export type PipelineStageReason = {
15
+ id: string;
16
+ name: string;
17
+ position: number;
18
+ isWon: boolean;
19
+ pipelineId: string;
20
+ stageId: string;
21
+ accountId: string;
22
+ createdAt: string;
23
+ updatedAt: string;
24
+ };
25
+ export type PipelineStage = {
26
+ id: string;
27
+ name: string;
28
+ position: number;
29
+ pipelineId: string;
30
+ accountId: string;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ deletedAt: string | null;
34
+ statuses?: PipelineStageStatus[];
35
+ reasons?: PipelineStageReason[];
36
+ /** Card totals — present on create/update/getById, absent on the listing `include`. */
37
+ totalCards?: number;
38
+ totalCardsValue?: number;
39
+ totalWonCardsValue?: number;
40
+ totalLostCardsValue?: number;
41
+ };
42
+ /** The pipeline row as stored — what the webhook events (`pipeline.created`/`.updated`) carry. */
43
+ export type PipelineRecord = {
3
44
  id: string;
4
45
  name: string;
5
46
  goBack: boolean;
@@ -9,16 +50,39 @@ export type Pipeline = {
9
50
  createdAt: string;
10
51
  updatedAt: string;
11
52
  deletedAt: string | null;
53
+ };
54
+ /**
55
+ * A sales funnel pipeline.
56
+ *
57
+ * `create`, `updateById` and `getById` answer the full entity, always with `stages`. The listing
58
+ * (`getMany`) goes through the backend transformer and only carries `id`, `name`, `goBack` and
59
+ * `archivedAt` (plus the included relationships) — hence the optional fields below.
60
+ */
61
+ export type Pipeline = {
62
+ id: string;
63
+ name: string;
64
+ goBack: boolean;
65
+ archivedAt: string | null;
66
+ accountId?: string;
67
+ permissionToViewCard?: boolean | null;
68
+ createdAt?: string;
69
+ updatedAt?: string;
70
+ deletedAt?: string | null;
71
+ stages?: PipelineStage[];
12
72
  departments?: Department[];
13
73
  };
14
- export type PipelineRelationships = 'departments';
74
+ export type PipelineRelationships = 'departments' | 'stages';
15
75
  export type CreatePipelinePayload = {
76
+ /** Up to 100 characters; must be unique in the account. */
16
77
  name: string;
78
+ /** `false` = only move forward, `true` = move forward and backward. */
17
79
  goBack?: boolean;
80
+ /** When `true`, non-admin users only see the cards they own. */
18
81
  permissionToViewCard?: boolean;
19
82
  };
20
83
  export type UpdatePipelinePayload = {
21
- name?: string;
84
+ /** Required by the backend on every update (400 `required` otherwise). */
85
+ name: string;
22
86
  goBack?: boolean;
23
87
  permissionToViewCard?: boolean | null;
24
88
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/pipeline/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,oBAAoB,EAAE,OAAO,GAAG,IAAI,CAAA;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAExB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAA;AAEjD,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oBAAoB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACtC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/pipeline/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,31 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  //#region src/core/BaseApiClient.ts
4
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5
+ /**
6
+ * Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with
7
+ * `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).
8
+ * Returns `null` when the body carries no field errors.
9
+ */
10
+ function parseValidationErrors(errors) {
11
+ if (!isRecord(errors)) return null;
12
+ const parsed = [];
13
+ for (const [location, fields] of Object.entries(errors)) {
14
+ if (!isRecord(fields)) continue;
15
+ for (const [field, detail] of Object.entries(fields)) {
16
+ const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : [];
17
+ const types = Array.isArray(detail?.types) ? detail.types.map(String) : [];
18
+ messages.forEach((message, index) => {
19
+ parsed.push({
20
+ path: `${location}.${field}`,
21
+ message,
22
+ code: types[index] ?? types[0] ?? ""
23
+ });
24
+ });
25
+ }
26
+ }
27
+ return parsed.length ? parsed : null;
28
+ }
4
29
  var ApiError = class extends Error {
5
30
  errorClass;
6
31
  status;
@@ -49,7 +74,7 @@ var BaseApiClient = class {
49
74
  const errorData = JSON.parse(errorText);
50
75
  errorMessage = errorData.message || errorData.error || errorMessage;
51
76
  errorClass = errorData.error;
52
- validationErrors = errorData.validationErrors ?? null;
77
+ validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors);
53
78
  }
54
79
  } catch {}
55
80
  throw new ApiError(errorMessage, errorClass, response.status, validationErrors);
@@ -1 +1 @@
1
- {"version":3,"file":"BaseApiClient.cjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\n\nexport interface ValidationError {\n path: string\n message: string\n code: string\n}\n\nexport class ApiError extends Error {\n public readonly errorClass?: string | undefined\n public readonly status?: number | undefined\n public readonly validationErrors: ValidationError[] | null\n\n constructor(\n message: string,\n errorClass?: string,\n status?: number,\n validationErrors: ValidationError[] | null = null,\n ) {\n super(message)\n this.name = 'ApiError'\n this.errorClass = errorClass\n this.status = status\n this.validationErrors = validationErrors\n }\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n\n constructor(baseUrl: string, accessToken?: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n })\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n let errorMessage = `HTTP Error ${response.status}: ${response.statusText}`\n let errorClass: string | undefined\n let validationErrors: ValidationError[] | null = null\n\n if (isJson) {\n try {\n const errorText = await response.text()\n if (errorText) {\n const errorData = JSON.parse(errorText)\n errorMessage = errorData.message || errorData.error || errorMessage\n errorClass = errorData.error\n validationErrors = errorData.validationErrors ?? null\n }\n } catch {\n // If JSON parsing fails, use the default error message\n }\n }\n\n throw new ApiError(errorMessage, errorClass, response.status, validationErrors)\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":";;;AAQA,IAAa,WAAb,cAA8B,MAAM;CAClC,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAEhB,YACE,SACA,YACA,QACA,mBAA6C,MAC7C;AACA,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,SAAS;AACd,OAAK,mBAAmB;;;AAI5B,IAAa,gBAAb,MAAgD;CAC9C,AAAmB;CACnB,AAAU,cAA6B;CAEvC,YAAY,SAAiB,aAAsB;AACjD,OAAK,UAAU,QAAQ,QAAQ,OAAO,GAAG;AACzC,OAAK,cAAc,eAAe;;CAGpC,eAAe,aAA2B;AACxC,OAAK,cAAc;AACnB,SAAO;;CAGT,MAAM,QACJ,QACA,UACA,MACA,SACoB;EACpB,MAAM,MAAM,GAAG,KAAK,QAAQ,GAAG,SAAS,QAAQ,OAAO,GAAG;EAE1D,MAAM,WAAW,MAAM,MAAM,KAAK;GAChC;GACA,SAAS;IACP,gBAAgB;IAChB,GAAI,KAAK,eAAe,EAAE,eAAe,UAAU,KAAK,eAAe;IACvE,GAAG;IACJ;GACD,GAAI,SAAS,UAAa,EAAE,MAAM,KAAK,UAAU,KAAK,EAAE;GACzD,CAAC;AAEF,SAAO,KAAK,eAA0B,SAAS;;CAGjD,MAAgB,eAA0B,UAAwC;AAChF,MAAI,CAAC,SAAS,IAAI;GAEhB,MAAM,SADc,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI;GAE5D,IAAI,eAAe,cAAc,SAAS,OAAO,IAAI,SAAS;GAC9D,IAAI;GACJ,IAAI,mBAA6C;AAEjD,OAAI,OACF,KAAI;IACF,MAAM,YAAY,MAAM,SAAS,MAAM;AACvC,QAAI,WAAW;KACb,MAAM,YAAY,KAAK,MAAM,UAAU;AACvC,oBAAe,UAAU,WAAW,UAAU,SAAS;AACvD,kBAAa,UAAU;AACvB,wBAAmB,UAAU,oBAAoB;;WAE7C;AAKV,SAAM,IAAI,SAAS,cAAc,YAAY,SAAS,QAAQ,iBAAiB;;AAIjF,MAAI,SAAS,WAAW,IACtB;EAQF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,MAAI,CAAC,KACH;AAMF,MAHoB,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI,MAG1D,QAAO,KAAK,MAAM,KAAK;AAGzB,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;CAIX,IAAyB,UAAkB,SAAsD;AAC/F,SAAO,KAAK,QAAmB,OAAO,UAAU,QAAW,QAAQ;;CAGrE,KACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,QAAQ,UAAU,MAAM,QAAQ;;CAGxE,IACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,OAAO,UAAU,MAAM,QAAQ;;CAGvE,MACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,SAAS,UAAU,MAAM,QAAQ;;CAGzE,OACE,UACA,SACoB;AACpB,SAAO,KAAK,QAAmB,UAAU,UAAU,QAAW,QAAQ"}
1
+ {"version":3,"file":"BaseApiClient.cjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\n\nexport interface ValidationError {\n path: string\n message: string\n code: string\n}\n\n/**\n * Digisac field errors: `{ errors: { <location>: { <field>: { messages: string[], types: string[] } } } }`,\n * where location is `body`, `params`, `query`, `headers` or `cookies` (backend `validate` middleware).\n */\ntype DigisacFieldErrors = Record<string, Record<string, { messages?: unknown; types?: unknown }>>\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with\n * `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).\n * Returns `null` when the body carries no field errors.\n */\nfunction parseValidationErrors(errors: unknown): ValidationError[] | null {\n if (!isRecord(errors)) {\n return null\n }\n\n const parsed: ValidationError[] = []\n for (const [location, fields] of Object.entries(errors as DigisacFieldErrors)) {\n if (!isRecord(fields)) {\n continue\n }\n for (const [field, detail] of Object.entries(fields)) {\n const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : []\n const types = Array.isArray(detail?.types) ? detail.types.map(String) : []\n messages.forEach((message, index) => {\n parsed.push({ path: `${location}.${field}`, message, code: types[index] ?? types[0] ?? '' })\n })\n }\n }\n\n return parsed.length ? parsed : null\n}\n\nexport class ApiError extends Error {\n public readonly errorClass?: string | undefined\n public readonly status?: number | undefined\n public readonly validationErrors: ValidationError[] | null\n\n constructor(\n message: string,\n errorClass?: string,\n status?: number,\n validationErrors: ValidationError[] | null = null,\n ) {\n super(message)\n this.name = 'ApiError'\n this.errorClass = errorClass\n this.status = status\n this.validationErrors = validationErrors\n }\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n\n constructor(baseUrl: string, accessToken?: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n })\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n let errorMessage = `HTTP Error ${response.status}: ${response.statusText}`\n let errorClass: string | undefined\n let validationErrors: ValidationError[] | null = null\n\n if (isJson) {\n try {\n const errorText = await response.text()\n if (errorText) {\n const errorData = JSON.parse(errorText)\n errorMessage = errorData.message || errorData.error || errorMessage\n errorClass = errorData.error\n validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors)\n }\n } catch {\n // If JSON parsing fails, use the default error message\n }\n }\n\n throw new ApiError(errorMessage, errorClass, response.status, validationErrors)\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseApiClient.d.ts","sourceRoot":"","sources":["../../src/core/BaseApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,SAAgB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3C,SAAgB,gBAAgB,EAAE,eAAe,EAAE,GAAG,IAAI,CAAA;gBAGxD,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,gBAAgB,GAAE,eAAe,EAAE,GAAG,IAAW;CAQpD;AAED,qBAAa,aAAc,YAAW,SAAS;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAClC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAO;gBAE/B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAKjD,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKnC,OAAO,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAChD,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;cAgBL,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAuDjF,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAIhG,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,KAAK,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,MAAM,CAAC,SAAS,GAAG,OAAO,EACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;CAGtB"}
1
+ {"version":3,"file":"BaseApiClient.d.ts","sourceRoot":"","sources":["../../src/core/BaseApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAsCD,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,SAAgB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3C,SAAgB,gBAAgB,EAAE,eAAe,EAAE,GAAG,IAAI,CAAA;gBAGxD,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,gBAAgB,GAAE,eAAe,EAAE,GAAG,IAAW;CAQpD;AAED,qBAAa,aAAc,YAAW,SAAS;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAClC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAO;gBAE/B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAKjD,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKnC,OAAO,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAChD,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;cAgBL,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAuDjF,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAIhG,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,KAAK,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,MAAM,CAAC,SAAS,GAAG,OAAO,EACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;CAGtB"}
@@ -1,4 +1,29 @@
1
1
  //#region src/core/BaseApiClient.ts
2
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3
+ /**
4
+ * Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with
5
+ * `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).
6
+ * Returns `null` when the body carries no field errors.
7
+ */
8
+ function parseValidationErrors(errors) {
9
+ if (!isRecord(errors)) return null;
10
+ const parsed = [];
11
+ for (const [location, fields] of Object.entries(errors)) {
12
+ if (!isRecord(fields)) continue;
13
+ for (const [field, detail] of Object.entries(fields)) {
14
+ const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : [];
15
+ const types = Array.isArray(detail?.types) ? detail.types.map(String) : [];
16
+ messages.forEach((message, index) => {
17
+ parsed.push({
18
+ path: `${location}.${field}`,
19
+ message,
20
+ code: types[index] ?? types[0] ?? ""
21
+ });
22
+ });
23
+ }
24
+ }
25
+ return parsed.length ? parsed : null;
26
+ }
2
27
  var ApiError = class extends Error {
3
28
  errorClass;
4
29
  status;
@@ -47,7 +72,7 @@ var BaseApiClient = class {
47
72
  const errorData = JSON.parse(errorText);
48
73
  errorMessage = errorData.message || errorData.error || errorMessage;
49
74
  errorClass = errorData.error;
50
- validationErrors = errorData.validationErrors ?? null;
75
+ validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors);
51
76
  }
52
77
  } catch {}
53
78
  throw new ApiError(errorMessage, errorClass, response.status, validationErrors);
@@ -1 +1 @@
1
- {"version":3,"file":"BaseApiClient.mjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\n\nexport interface ValidationError {\n path: string\n message: string\n code: string\n}\n\nexport class ApiError extends Error {\n public readonly errorClass?: string | undefined\n public readonly status?: number | undefined\n public readonly validationErrors: ValidationError[] | null\n\n constructor(\n message: string,\n errorClass?: string,\n status?: number,\n validationErrors: ValidationError[] | null = null,\n ) {\n super(message)\n this.name = 'ApiError'\n this.errorClass = errorClass\n this.status = status\n this.validationErrors = validationErrors\n }\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n\n constructor(baseUrl: string, accessToken?: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n })\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n let errorMessage = `HTTP Error ${response.status}: ${response.statusText}`\n let errorClass: string | undefined\n let validationErrors: ValidationError[] | null = null\n\n if (isJson) {\n try {\n const errorText = await response.text()\n if (errorText) {\n const errorData = JSON.parse(errorText)\n errorMessage = errorData.message || errorData.error || errorMessage\n errorClass = errorData.error\n validationErrors = errorData.validationErrors ?? null\n }\n } catch {\n // If JSON parsing fails, use the default error message\n }\n }\n\n throw new ApiError(errorMessage, errorClass, response.status, validationErrors)\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":";AAQA,IAAa,WAAb,cAA8B,MAAM;CAClC,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAEhB,YACE,SACA,YACA,QACA,mBAA6C,MAC7C;AACA,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,SAAS;AACd,OAAK,mBAAmB;;;AAI5B,IAAa,gBAAb,MAAgD;CAC9C,AAAmB;CACnB,AAAU,cAA6B;CAEvC,YAAY,SAAiB,aAAsB;AACjD,OAAK,UAAU,QAAQ,QAAQ,OAAO,GAAG;AACzC,OAAK,cAAc,eAAe;;CAGpC,eAAe,aAA2B;AACxC,OAAK,cAAc;AACnB,SAAO;;CAGT,MAAM,QACJ,QACA,UACA,MACA,SACoB;EACpB,MAAM,MAAM,GAAG,KAAK,QAAQ,GAAG,SAAS,QAAQ,OAAO,GAAG;EAE1D,MAAM,WAAW,MAAM,MAAM,KAAK;GAChC;GACA,SAAS;IACP,gBAAgB;IAChB,GAAI,KAAK,eAAe,EAAE,eAAe,UAAU,KAAK,eAAe;IACvE,GAAG;IACJ;GACD,GAAI,SAAS,UAAa,EAAE,MAAM,KAAK,UAAU,KAAK,EAAE;GACzD,CAAC;AAEF,SAAO,KAAK,eAA0B,SAAS;;CAGjD,MAAgB,eAA0B,UAAwC;AAChF,MAAI,CAAC,SAAS,IAAI;GAEhB,MAAM,SADc,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI;GAE5D,IAAI,eAAe,cAAc,SAAS,OAAO,IAAI,SAAS;GAC9D,IAAI;GACJ,IAAI,mBAA6C;AAEjD,OAAI,OACF,KAAI;IACF,MAAM,YAAY,MAAM,SAAS,MAAM;AACvC,QAAI,WAAW;KACb,MAAM,YAAY,KAAK,MAAM,UAAU;AACvC,oBAAe,UAAU,WAAW,UAAU,SAAS;AACvD,kBAAa,UAAU;AACvB,wBAAmB,UAAU,oBAAoB;;WAE7C;AAKV,SAAM,IAAI,SAAS,cAAc,YAAY,SAAS,QAAQ,iBAAiB;;AAIjF,MAAI,SAAS,WAAW,IACtB;EAQF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,MAAI,CAAC,KACH;AAMF,MAHoB,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI,MAG1D,QAAO,KAAK,MAAM,KAAK;AAGzB,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;CAIX,IAAyB,UAAkB,SAAsD;AAC/F,SAAO,KAAK,QAAmB,OAAO,UAAU,QAAW,QAAQ;;CAGrE,KACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,QAAQ,UAAU,MAAM,QAAQ;;CAGxE,IACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,OAAO,UAAU,MAAM,QAAQ;;CAGvE,MACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,SAAS,UAAU,MAAM,QAAQ;;CAGzE,OACE,UACA,SACoB;AACpB,SAAO,KAAK,QAAmB,UAAU,UAAU,QAAW,QAAQ"}
1
+ {"version":3,"file":"BaseApiClient.mjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\n\nexport interface ValidationError {\n path: string\n message: string\n code: string\n}\n\n/**\n * Digisac field errors: `{ errors: { <location>: { <field>: { messages: string[], types: string[] } } } }`,\n * where location is `body`, `params`, `query`, `headers` or `cookies` (backend `validate` middleware).\n */\ntype DigisacFieldErrors = Record<string, Record<string, { messages?: unknown; types?: unknown }>>\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with\n * `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).\n * Returns `null` when the body carries no field errors.\n */\nfunction parseValidationErrors(errors: unknown): ValidationError[] | null {\n if (!isRecord(errors)) {\n return null\n }\n\n const parsed: ValidationError[] = []\n for (const [location, fields] of Object.entries(errors as DigisacFieldErrors)) {\n if (!isRecord(fields)) {\n continue\n }\n for (const [field, detail] of Object.entries(fields)) {\n const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : []\n const types = Array.isArray(detail?.types) ? detail.types.map(String) : []\n messages.forEach((message, index) => {\n parsed.push({ path: `${location}.${field}`, message, code: types[index] ?? types[0] ?? '' })\n })\n }\n }\n\n return parsed.length ? parsed : null\n}\n\nexport class ApiError extends Error {\n public readonly errorClass?: string | undefined\n public readonly status?: number | undefined\n public readonly validationErrors: ValidationError[] | null\n\n constructor(\n message: string,\n errorClass?: string,\n status?: number,\n validationErrors: ValidationError[] | null = null,\n ) {\n super(message)\n this.name = 'ApiError'\n this.errorClass = errorClass\n this.status = status\n this.validationErrors = validationErrors\n }\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n\n constructor(baseUrl: string, accessToken?: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n })\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n let errorMessage = `HTTP Error ${response.status}: ${response.statusText}`\n let errorClass: string | undefined\n let validationErrors: ValidationError[] | null = null\n\n if (isJson) {\n try {\n const errorText = await response.text()\n if (errorText) {\n const errorData = JSON.parse(errorText)\n errorMessage = errorData.message || errorData.error || errorMessage\n errorClass = errorData.error\n validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors)\n }\n } catch {\n // If JSON parsing fails, use the default error message\n }\n }\n\n throw new ApiError(errorMessage, errorClass, response.status, validationErrors)\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ import type { Department, DepartmentRelationships } from '../apis/departments';
5
5
  import type { Message, MessageRelationships } from '../apis/messages';
6
6
  import type { Organization, OrganizationRelationships } from '../apis/organizations';
7
7
  import type { Person, PersonRelationships } from '../apis/people';
8
- import type { Pipeline, PipelineRelationships } from '../apis/pipeline';
8
+ import type { PipelineRecord } from '../apis/pipeline';
9
9
  import type { QuickReply, QuickReplyRelationships } from '../apis/quickReplies';
10
10
  import type { Role, RoleRelationships } from '../apis/roles';
11
11
  import type { Service, ServiceRelationships } from '../apis/services';
@@ -66,8 +66,8 @@ export interface WebhookEventPayloadMap {
66
66
  'campaign.created': Omit<Campaign, CampaignRelationships>;
67
67
  'campaign.updated': Omit<Campaign, CampaignRelationships>;
68
68
  'campaign.destroyed': Omit<Campaign, CampaignRelationships>;
69
- 'pipeline.created': Omit<Pipeline, PipelineRelationships>;
70
- 'pipeline.updated': Omit<Pipeline, PipelineRelationships>;
69
+ 'pipeline.created': PipelineRecord;
70
+ 'pipeline.updated': PipelineRecord;
71
71
  }
72
72
  export type WebhookPayload<E extends WebhookEvent = WebhookEvent> = {
73
73
  event: E;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/incommingWebhooks/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/incommingWebhooks/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikatec/digisac-api-sdk",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -1,14 +1,79 @@
1
1
  import type { Contact } from '../contacts/types'
2
- import type { Pipeline } from '../pipeline/types'
2
+ import type {
3
+ Pipeline,
4
+ PipelineStage,
5
+ PipelineStageReason,
6
+ PipelineStageStatus,
7
+ } from '../pipeline/types'
3
8
  import type { User } from '../users/types'
4
9
 
10
+ type NamedRef = { id: string; name: string }
11
+
12
+ /** One entry of the card history — written on create and on every stage/status/owner change. */
13
+ export type CardMovement = {
14
+ id: string
15
+ cardId: string
16
+ accountId: string
17
+ /** The user who made the change (the requester), not the card owner. */
18
+ userId: string
19
+ pipelineId: string
20
+ fromPipelineId: string | null
21
+ toPipelineId: string | null
22
+ fromPipelineStageId: string | null
23
+ toPipelineStageId: string | null
24
+ fromStageStatusId: string | null
25
+ toStageStatusId: string | null
26
+ fromOwnerId: string | null
27
+ toOwnerId: string | null
28
+ createdAt: string
29
+ // relationships (GET /cards/{id})
30
+ user?: NamedRef | null
31
+ from_pipeline?: NamedRef | null
32
+ to_pipeline?: NamedRef | null
33
+ from_pipeline_stage?: NamedRef | null
34
+ to_pipeline_stage?: NamedRef | null
35
+ from_stage_status?: NamedRef | null
36
+ to_stage_status?: NamedRef | null
37
+ from_owner?: NamedRef | null
38
+ to_owner?: NamedRef | null
39
+ }
40
+
41
+ export type CardProduct = {
42
+ id: string
43
+ cardId: string
44
+ name: string
45
+ /** Quantity (the backend column is spelled `ammount`). */
46
+ ammount: number
47
+ value: number
48
+ createdAt: string
49
+ updatedAt: string
50
+ }
51
+
52
+ export type CardComment = {
53
+ id: string
54
+ cardId: string
55
+ userId: string | null
56
+ comment: string | null
57
+ createdAt: string
58
+ updatedAt: string
59
+ user?: User | null
60
+ files?: Record<string, unknown>[]
61
+ }
62
+
63
+ /**
64
+ * A sales funnel card (opportunity).
65
+ *
66
+ * `create` and `updateById` answer the raw entity (with `updatedAt`/`archivedAt`). `getMany` and
67
+ * `getById` go through the backend transformer: no `updatedAt`/`archivedAt`, plus `url`,
68
+ * `lastMessage` and `totalValue`; `getById` also joins the relationships below.
69
+ */
5
70
  export type Card = {
6
71
  id: string
7
72
  title: string
8
73
  description: string | null
74
+ /** Position in the stage — set by the backend to the number of cards already in it. */
9
75
  order: number | null
10
76
  isArchived: boolean
11
- archivedAt: string | null
12
77
  success: boolean | null
13
78
  finishedAt: string | null
14
79
  organization: string | null
@@ -23,41 +88,73 @@ export type Card = {
23
88
  reasonId: string | null
24
89
  ownerId: string | null
25
90
  createdAt: string
26
- updatedAt: string
91
+ /** Only on create/update answers. */
92
+ updatedAt?: string
93
+ /** Only on create/update answers. */
94
+ archivedAt?: string | null
95
+ /** Only on getMany/getById answers (contact avatar URL, or empty string). */
96
+ url?: unknown
97
+ /** Only on getMany/getById answers (contact last message, or empty string). */
98
+ lastMessage?: unknown
99
+ /** Only on getMany/getById answers: sum of the products (`ammount * value`). */
100
+ totalValue?: number
27
101
  // relationships
28
102
  contact?: Contact | null
29
103
  owner?: User | null
30
104
  pipeline?: Pipeline
105
+ pipeline_stage?: PipelineStage | null
106
+ stage_status?: PipelineStageStatus | null
107
+ stage_reason?: PipelineStageReason | null
108
+ movements?: CardMovement[]
109
+ products?: CardProduct[]
110
+ comments?: CardComment[]
31
111
  }
32
112
 
33
- export type CardRelationships = 'contact' | 'owner' | 'pipeline'
113
+ export type CardRelationships =
114
+ | 'contact'
115
+ | 'owner'
116
+ | 'pipeline'
117
+ | 'pipeline_stage'
118
+ | 'stage_status'
119
+ | 'stage_reason'
120
+ | 'movements'
121
+ | 'products'
122
+ | 'comments'
34
123
 
35
124
  export type CreateCardPayload = {
125
+ /** Up to 255 characters. */
36
126
  title: string
37
127
  pipelineId: string
38
- contactId?: string
39
- pipelineStageId?: string
128
+ contactId: string
129
+ /** Must be a stage of `pipelineId`. */
130
+ pipelineStageId: string
40
131
  description?: string
132
+ ownerId?: string
133
+ statusId?: string
134
+ reasonId?: string
41
135
  organization?: string
42
136
  organizationSegment?: string
43
137
  originChannel?: string
44
138
  originCampaign?: string
45
- ownerId?: string
46
139
  }
47
140
 
48
141
  export type UpdateCardPayload = {
49
142
  title?: string
50
143
  description?: string | null
51
144
  contactId?: string | null
145
+ /** Moves the card to another pipeline (send the target `pipelineStageId` along). */
146
+ pipelineId?: string
52
147
  pipelineStageId?: string | null
53
148
  statusId?: string | null
54
149
  reasonId?: string | null
55
150
  ownerId?: string | null
151
+ order?: number
56
152
  organization?: string | null
57
153
  organizationSegment?: string | null
58
154
  originChannel?: string | null
59
155
  originCampaign?: string | null
60
156
  isArchived?: boolean
157
+ /** Marks the card as won (`true`) or lost (`false`); the backend fills `finishedAt`. */
61
158
  success?: boolean | null
62
159
  finishedAt?: string | null
63
160
  }
@@ -1,6 +1,50 @@
1
1
  import type { Department } from '../departments/types'
2
2
 
3
- export type Pipeline = {
3
+ export type PipelineStageStatus = {
4
+ id: string
5
+ /** The default "Finalizados" stage carries `STATUS_WON` and `STATUS_LOOSE`. */
6
+ name: string
7
+ position: number
8
+ pipelineId: string
9
+ stageId: string
10
+ accountId: string
11
+ createdAt: string
12
+ updatedAt: string
13
+ deletedAt: string | null
14
+ }
15
+
16
+ export type PipelineStageReason = {
17
+ id: string
18
+ name: string
19
+ position: number
20
+ isWon: boolean
21
+ pipelineId: string
22
+ stageId: string
23
+ accountId: string
24
+ createdAt: string
25
+ updatedAt: string
26
+ }
27
+
28
+ export type PipelineStage = {
29
+ id: string
30
+ name: string
31
+ position: number
32
+ pipelineId: string
33
+ accountId: string
34
+ createdAt: string
35
+ updatedAt: string
36
+ deletedAt: string | null
37
+ statuses?: PipelineStageStatus[]
38
+ reasons?: PipelineStageReason[]
39
+ /** Card totals — present on create/update/getById, absent on the listing `include`. */
40
+ totalCards?: number
41
+ totalCardsValue?: number
42
+ totalWonCardsValue?: number
43
+ totalLostCardsValue?: number
44
+ }
45
+
46
+ /** The pipeline row as stored — what the webhook events (`pipeline.created`/`.updated`) carry. */
47
+ export type PipelineRecord = {
4
48
  id: string
5
49
  name: string
6
50
  goBack: boolean
@@ -10,20 +54,44 @@ export type Pipeline = {
10
54
  createdAt: string
11
55
  updatedAt: string
12
56
  deletedAt: string | null
57
+ }
58
+
59
+ /**
60
+ * A sales funnel pipeline.
61
+ *
62
+ * `create`, `updateById` and `getById` answer the full entity, always with `stages`. The listing
63
+ * (`getMany`) goes through the backend transformer and only carries `id`, `name`, `goBack` and
64
+ * `archivedAt` (plus the included relationships) — hence the optional fields below.
65
+ */
66
+ export type Pipeline = {
67
+ id: string
68
+ name: string
69
+ goBack: boolean
70
+ archivedAt: string | null
71
+ accountId?: string
72
+ permissionToViewCard?: boolean | null
73
+ createdAt?: string
74
+ updatedAt?: string
75
+ deletedAt?: string | null
13
76
  // relationships
77
+ stages?: PipelineStage[]
14
78
  departments?: Department[]
15
79
  }
16
80
 
17
- export type PipelineRelationships = 'departments'
81
+ export type PipelineRelationships = 'departments' | 'stages'
18
82
 
19
83
  export type CreatePipelinePayload = {
84
+ /** Up to 100 characters; must be unique in the account. */
20
85
  name: string
86
+ /** `false` = only move forward, `true` = move forward and backward. */
21
87
  goBack?: boolean
88
+ /** When `true`, non-admin users only see the cards they own. */
22
89
  permissionToViewCard?: boolean
23
90
  }
24
91
 
25
92
  export type UpdatePipelinePayload = {
26
- name?: string
93
+ /** Required by the backend on every update (400 `required` otherwise). */
94
+ name: string
27
95
  goBack?: boolean
28
96
  permissionToViewCard?: boolean | null
29
97
  }
@@ -230,6 +230,59 @@ describe('BaseApiClient', () => {
230
230
  })
231
231
  })
232
232
 
233
+ it('maps the Digisac field errors (errors.<location>.<field>) into validationErrors', async () => {
234
+ mockFetch({
235
+ ok: false,
236
+ status: 400,
237
+ statusText: 'Bad Request',
238
+ headers: { 'Content-Type': 'application/json' },
239
+ body: JSON.stringify({
240
+ error: 'ValidationError',
241
+ message: 'The given data was invalid.',
242
+ status: 400,
243
+ errors: {
244
+ body: {
245
+ name: { messages: ['Required.'], types: ['required'] },
246
+ title: {
247
+ messages: ['Required.', 'Should contain lesser than or equals 255 characters.'],
248
+ types: ['required', 'hasLengthLesserThanOrEqual'],
249
+ },
250
+ },
251
+ params: { contactId: { messages: ['Should be an UUID v4 string.'], types: ['uuid4'] } },
252
+ },
253
+ }),
254
+ })
255
+ await expect(client.post('/fail', {})).rejects.toMatchObject({
256
+ errorClass: 'ValidationError',
257
+ status: 400,
258
+ validationErrors: [
259
+ { path: 'body.name', message: 'Required.', code: 'required' },
260
+ { path: 'body.title', message: 'Required.', code: 'required' },
261
+ {
262
+ path: 'body.title',
263
+ message: 'Should contain lesser than or equals 255 characters.',
264
+ code: 'hasLengthLesserThanOrEqual',
265
+ },
266
+ { path: 'params.contactId', message: 'Should be an UUID v4 string.', code: 'uuid4' },
267
+ ],
268
+ })
269
+ })
270
+
271
+ it('keeps validationErrors null when the error body has no field errors', async () => {
272
+ mockFetch({
273
+ ok: false,
274
+ status: 400,
275
+ statusText: 'Bad Request',
276
+ headers: { 'Content-Type': 'application/json' },
277
+ body: JSON.stringify({
278
+ error: 'BadRequestHttpError',
279
+ message: 'Já existe uma funil com esse nome',
280
+ status: 400,
281
+ }),
282
+ })
283
+ await expect(client.get('/fail')).rejects.toMatchObject({ validationErrors: null })
284
+ })
285
+
233
286
  it('falls back to default message when JSON parsing fails', async () => {
234
287
  mockFetch({
235
288
  ok: false,
@@ -6,6 +6,42 @@ export interface ValidationError {
6
6
  code: string
7
7
  }
8
8
 
9
+ /**
10
+ * Digisac field errors: `{ errors: { <location>: { <field>: { messages: string[], types: string[] } } } }`,
11
+ * where location is `body`, `params`, `query`, `headers` or `cookies` (backend `validate` middleware).
12
+ */
13
+ type DigisacFieldErrors = Record<string, Record<string, { messages?: unknown; types?: unknown }>>
14
+
15
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
16
+ typeof value === 'object' && value !== null && !Array.isArray(value)
17
+
18
+ /**
19
+ * Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with
20
+ * `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).
21
+ * Returns `null` when the body carries no field errors.
22
+ */
23
+ function parseValidationErrors(errors: unknown): ValidationError[] | null {
24
+ if (!isRecord(errors)) {
25
+ return null
26
+ }
27
+
28
+ const parsed: ValidationError[] = []
29
+ for (const [location, fields] of Object.entries(errors as DigisacFieldErrors)) {
30
+ if (!isRecord(fields)) {
31
+ continue
32
+ }
33
+ for (const [field, detail] of Object.entries(fields)) {
34
+ const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : []
35
+ const types = Array.isArray(detail?.types) ? detail.types.map(String) : []
36
+ messages.forEach((message, index) => {
37
+ parsed.push({ path: `${location}.${field}`, message, code: types[index] ?? types[0] ?? '' })
38
+ })
39
+ }
40
+ }
41
+
42
+ return parsed.length ? parsed : null
43
+ }
44
+
9
45
  export class ApiError extends Error {
10
46
  public readonly errorClass?: string | undefined
11
47
  public readonly status?: number | undefined
@@ -76,7 +112,7 @@ export class BaseApiClient implements ApiClient {
76
112
  const errorData = JSON.parse(errorText)
77
113
  errorMessage = errorData.message || errorData.error || errorMessage
78
114
  errorClass = errorData.error
79
- validationErrors = errorData.validationErrors ?? null
115
+ validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors)
80
116
  }
81
117
  } catch {
82
118
  // If JSON parsing fails, use the default error message
@@ -5,7 +5,7 @@ import type { Department, DepartmentRelationships } from '../apis/departments'
5
5
  import type { Message, MessageRelationships } from '../apis/messages'
6
6
  import type { Organization, OrganizationRelationships } from '../apis/organizations'
7
7
  import type { Person, PersonRelationships } from '../apis/people'
8
- import type { Pipeline, PipelineRelationships } from '../apis/pipeline'
8
+ import type { PipelineRecord } from '../apis/pipeline'
9
9
  import type { QuickReply, QuickReplyRelationships } from '../apis/quickReplies'
10
10
  import type { Role, RoleRelationships } from '../apis/roles'
11
11
  import type { Service, ServiceRelationships } from '../apis/services'
@@ -119,8 +119,8 @@ export interface WebhookEventPayloadMap {
119
119
  'campaign.created': Omit<Campaign, CampaignRelationships>
120
120
  'campaign.updated': Omit<Campaign, CampaignRelationships>
121
121
  'campaign.destroyed': Omit<Campaign, CampaignRelationships>
122
- 'pipeline.created': Omit<Pipeline, PipelineRelationships>
123
- 'pipeline.updated': Omit<Pipeline, PipelineRelationships>
122
+ 'pipeline.created': PipelineRecord
123
+ 'pipeline.updated': PipelineRecord
124
124
  }
125
125
 
126
126
  // ─── Webhook Envelope ────────────────────────────────────────────────────────