@decaf-ts/integrations 0.12.0 → 0.14.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.
- package/dist/integrations.cjs +1 -1
- package/lib/cjs/calendar/environment.cjs +48 -0
- package/lib/cjs/calendar/environment.cjs.map +1 -0
- package/lib/cjs/calendar/google-calendar/GoogleCalendarService.cjs +338 -0
- package/lib/cjs/calendar/google-calendar/GoogleCalendarService.cjs.map +1 -0
- package/lib/cjs/calendar/google-calendar/index.cjs +20 -0
- package/lib/cjs/calendar/google-calendar/index.cjs.map +1 -0
- package/lib/cjs/comms/discord/DiscordService.cjs +318 -0
- package/lib/cjs/comms/discord/DiscordService.cjs.map +1 -0
- package/lib/cjs/comms/discord/index.cjs +19 -0
- package/lib/cjs/comms/discord/index.cjs.map +1 -0
- package/lib/cjs/comms/environment.cjs +16 -0
- package/lib/cjs/comms/environment.cjs.map +1 -1
- package/lib/cjs/comms/index.cjs +3 -0
- package/lib/cjs/comms/index.cjs.map +1 -1
- package/lib/cjs/comms/outlook/MicrosoftOutlookService.cjs +325 -0
- package/lib/cjs/comms/outlook/MicrosoftOutlookService.cjs.map +1 -0
- package/lib/cjs/comms/outlook/index.cjs +19 -0
- package/lib/cjs/comms/outlook/index.cjs.map +1 -0
- package/lib/cjs/comms/whatsapp/WhatsAppService.cjs +274 -0
- package/lib/cjs/comms/whatsapp/WhatsAppService.cjs.map +1 -0
- package/lib/cjs/comms/whatsapp/index.cjs +19 -0
- package/lib/cjs/comms/whatsapp/index.cjs.map +1 -0
- package/lib/cjs/index.cjs +3 -3
- package/lib/cjs/io/confluence/ConfluenceService.cjs +317 -0
- package/lib/cjs/io/confluence/ConfluenceService.cjs.map +1 -0
- package/lib/cjs/io/confluence/index.cjs +19 -0
- package/lib/cjs/io/confluence/index.cjs.map +1 -0
- package/lib/cjs/io/environment.cjs +28 -0
- package/lib/cjs/io/environment.cjs.map +1 -1
- package/lib/cjs/io/google-docs/GoogleDocsService.cjs +275 -0
- package/lib/cjs/io/google-docs/GoogleDocsService.cjs.map +1 -0
- package/lib/cjs/io/google-docs/index.cjs +19 -0
- package/lib/cjs/io/google-docs/index.cjs.map +1 -0
- package/lib/cjs/io/index.cjs +5 -0
- package/lib/cjs/io/index.cjs.map +1 -1
- package/lib/cjs/io/jira/JiraService.cjs +354 -0
- package/lib/cjs/io/jira/JiraService.cjs.map +1 -0
- package/lib/cjs/io/jira/index.cjs +19 -0
- package/lib/cjs/io/jira/index.cjs.map +1 -0
- package/lib/cjs/io/microsoft-excel/MicrosoftExcelService.cjs +253 -0
- package/lib/cjs/io/microsoft-excel/MicrosoftExcelService.cjs.map +1 -0
- package/lib/cjs/io/microsoft-excel/index.cjs +19 -0
- package/lib/cjs/io/microsoft-excel/index.cjs.map +1 -0
- package/lib/cjs/io/microsoft-sharepoint/MicrosoftSharePointService.cjs +261 -0
- package/lib/cjs/io/microsoft-sharepoint/MicrosoftSharePointService.cjs.map +1 -0
- package/lib/cjs/io/microsoft-sharepoint/index.cjs +19 -0
- package/lib/cjs/io/microsoft-sharepoint/index.cjs.map +1 -0
- package/lib/esm/calendar/environment.js +44 -0
- package/lib/esm/calendar/environment.js.map +1 -0
- package/lib/esm/calendar/google-calendar/GoogleCalendarService.js +333 -0
- package/lib/esm/calendar/google-calendar/GoogleCalendarService.js.map +1 -0
- package/lib/esm/calendar/google-calendar/index.js +3 -0
- package/lib/esm/calendar/google-calendar/index.js.map +1 -0
- package/lib/esm/comms/discord/DiscordService.js +313 -0
- package/lib/esm/comms/discord/DiscordService.js.map +1 -0
- package/lib/esm/comms/discord/index.js +2 -0
- package/lib/esm/comms/discord/index.js.map +1 -0
- package/lib/esm/comms/environment.js +16 -0
- package/lib/esm/comms/environment.js.map +1 -1
- package/lib/esm/comms/index.js +3 -0
- package/lib/esm/comms/index.js.map +1 -1
- package/lib/esm/comms/outlook/MicrosoftOutlookService.js +320 -0
- package/lib/esm/comms/outlook/MicrosoftOutlookService.js.map +1 -0
- package/lib/esm/comms/outlook/index.js +2 -0
- package/lib/esm/comms/outlook/index.js.map +1 -0
- package/lib/esm/comms/whatsapp/WhatsAppService.js +269 -0
- package/lib/esm/comms/whatsapp/WhatsAppService.js.map +1 -0
- package/lib/esm/comms/whatsapp/index.js +2 -0
- package/lib/esm/comms/whatsapp/index.js.map +1 -0
- package/lib/esm/index.js +3 -3
- package/lib/esm/io/confluence/ConfluenceService.js +312 -0
- package/lib/esm/io/confluence/ConfluenceService.js.map +1 -0
- package/lib/esm/io/confluence/index.js +2 -0
- package/lib/esm/io/confluence/index.js.map +1 -0
- package/lib/esm/io/environment.js +28 -0
- package/lib/esm/io/environment.js.map +1 -1
- package/lib/esm/io/google-docs/GoogleDocsService.js +270 -0
- package/lib/esm/io/google-docs/GoogleDocsService.js.map +1 -0
- package/lib/esm/io/google-docs/index.js +2 -0
- package/lib/esm/io/google-docs/index.js.map +1 -0
- package/lib/esm/io/index.js +5 -0
- package/lib/esm/io/index.js.map +1 -1
- package/lib/esm/io/jira/JiraService.js +349 -0
- package/lib/esm/io/jira/JiraService.js.map +1 -0
- package/lib/esm/io/jira/index.js +2 -0
- package/lib/esm/io/jira/index.js.map +1 -0
- package/lib/esm/io/microsoft-excel/MicrosoftExcelService.js +248 -0
- package/lib/esm/io/microsoft-excel/MicrosoftExcelService.js.map +1 -0
- package/lib/esm/io/microsoft-excel/index.js +2 -0
- package/lib/esm/io/microsoft-excel/index.js.map +1 -0
- package/lib/esm/io/microsoft-sharepoint/MicrosoftSharePointService.js +256 -0
- package/lib/esm/io/microsoft-sharepoint/MicrosoftSharePointService.js.map +1 -0
- package/lib/esm/io/microsoft-sharepoint/index.js +2 -0
- package/lib/esm/io/microsoft-sharepoint/index.js.map +1 -0
- package/lib/types/calendar/environment.d.cts +48 -0
- package/lib/types/calendar/environment.d.mts +48 -0
- package/lib/types/calendar/google-calendar/GoogleCalendarService.d.cts +316 -0
- package/lib/types/calendar/google-calendar/GoogleCalendarService.d.mts +316 -0
- package/lib/types/calendar/google-calendar/index.d.cts +2 -0
- package/lib/types/calendar/google-calendar/index.d.mts +2 -0
- package/lib/types/comms/discord/DiscordService.d.cts +285 -0
- package/lib/types/comms/discord/DiscordService.d.mts +285 -0
- package/lib/types/comms/discord/index.d.cts +1 -0
- package/lib/types/comms/discord/index.d.mts +1 -0
- package/lib/types/comms/environment.d.cts +34 -8
- package/lib/types/comms/environment.d.mts +34 -8
- package/lib/types/comms/index.d.cts +3 -0
- package/lib/types/comms/index.d.mts +3 -0
- package/lib/types/comms/outlook/MicrosoftOutlookService.d.cts +282 -0
- package/lib/types/comms/outlook/MicrosoftOutlookService.d.mts +282 -0
- package/lib/types/comms/outlook/index.d.cts +1 -0
- package/lib/types/comms/outlook/index.d.mts +1 -0
- package/lib/types/comms/whatsapp/WhatsAppService.d.cts +258 -0
- package/lib/types/comms/whatsapp/WhatsAppService.d.mts +258 -0
- package/lib/types/comms/whatsapp/index.d.cts +1 -0
- package/lib/types/comms/whatsapp/index.d.mts +1 -0
- package/lib/types/index.d.cts +2 -2
- package/lib/types/index.d.mts +2 -2
- package/lib/types/io/confluence/ConfluenceService.d.cts +250 -0
- package/lib/types/io/confluence/ConfluenceService.d.mts +250 -0
- package/lib/types/io/confluence/index.d.cts +1 -0
- package/lib/types/io/confluence/index.d.mts +1 -0
- package/lib/types/io/environment.d.cts +52 -12
- package/lib/types/io/environment.d.mts +52 -12
- package/lib/types/io/google-docs/GoogleDocsService.d.cts +188 -0
- package/lib/types/io/google-docs/GoogleDocsService.d.mts +188 -0
- package/lib/types/io/google-docs/index.d.cts +1 -0
- package/lib/types/io/google-docs/index.d.mts +1 -0
- package/lib/types/io/index.d.cts +5 -0
- package/lib/types/io/index.d.mts +5 -0
- package/lib/types/io/jira/JiraService.d.cts +300 -0
- package/lib/types/io/jira/JiraService.d.mts +300 -0
- package/lib/types/io/jira/index.d.cts +1 -0
- package/lib/types/io/jira/index.d.mts +1 -0
- package/lib/types/io/microsoft-excel/MicrosoftExcelService.d.cts +230 -0
- package/lib/types/io/microsoft-excel/MicrosoftExcelService.d.mts +230 -0
- package/lib/types/io/microsoft-excel/index.d.cts +1 -0
- package/lib/types/io/microsoft-excel/index.d.mts +1 -0
- package/lib/types/io/microsoft-sharepoint/MicrosoftSharePointService.d.cts +226 -0
- package/lib/types/io/microsoft-sharepoint/MicrosoftSharePointService.d.mts +226 -0
- package/lib/types/io/microsoft-sharepoint/index.d.cts +1 -0
- package/lib/types/io/microsoft-sharepoint/index.d.mts +1 -0
- package/package.json +101 -5
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/comms/whatsapp/service
|
|
3
|
+
* @summary WhatsApp Cloud API integration service for text, template, and media messages.
|
|
4
|
+
* @description Exposes the Meta WhatsApp Cloud API (Graph `v19.0`) as an
|
|
5
|
+
* undecorated client-based service built on {@link HttpApiService}.
|
|
6
|
+
* Configuration comes from an explicit `WhatsAppServiceConfig` or the
|
|
7
|
+
* `comms.whatsApp` environment slice; the access token is sent as
|
|
8
|
+
* `Authorization: Bearer <token>` and the sender is identified by the
|
|
9
|
+
* configured `phoneNumberId`. Credentials are referenced from configuration
|
|
10
|
+
* (and, from as-graph nodes, from the resolved `whatsapp` credential secret)
|
|
11
|
+
* and are never embedded in source. Failures are mapped to decaf errors via
|
|
12
|
+
* {@link httpError}.
|
|
13
|
+
*/
|
|
14
|
+
import { InternalError } from "@decaf-ts/db-decorators";
|
|
15
|
+
import { CommsEnvironment } from "./../environment.js";
|
|
16
|
+
import { envNumber, envString } from "./../../shared/environmentValue.js";
|
|
17
|
+
import { HttpApiService, httpError, } from "./../../shared/http/index.js";
|
|
18
|
+
/**
|
|
19
|
+
* @description WhatsApp Cloud API integration service
|
|
20
|
+
* @summary An undecorated HTTP service for text, template, and media
|
|
21
|
+
* messages, read receipts, and media metadata. Every message operation needs
|
|
22
|
+
* both the access token and the sender phone number ID; missing credentials or
|
|
23
|
+
* identifiers raise `InternalError`, and transport failures are mapped to decaf
|
|
24
|
+
* errors via {@link httpError}.
|
|
25
|
+
* @class WhatsAppService
|
|
26
|
+
* @extends HttpApiService
|
|
27
|
+
* @category Comms
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { WhatsAppService } from "@decaf-ts/integrations/comms/whatsapp";
|
|
31
|
+
*
|
|
32
|
+
* const whatsapp = new WhatsAppService();
|
|
33
|
+
* await whatsapp.initialize({
|
|
34
|
+
* token: process.env.GRAPH_CREDENTIAL_WHATSAPP_TOKEN,
|
|
35
|
+
* phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID,
|
|
36
|
+
* });
|
|
37
|
+
* await whatsapp.sendText({ to: "15551234567", text: "Hello" });
|
|
38
|
+
* ```
|
|
39
|
+
* @mermaid
|
|
40
|
+
* sequenceDiagram
|
|
41
|
+
* autonumber
|
|
42
|
+
* participant Caller
|
|
43
|
+
* participant Service as WhatsAppService
|
|
44
|
+
* participant Graph as WhatsApp Cloud API
|
|
45
|
+
* Caller->>Service: sendText(input)
|
|
46
|
+
* activate Service
|
|
47
|
+
* Service->>Service: requireTokenAndPhone()
|
|
48
|
+
* Service->>Graph: POST /{phoneNumberId}/messages
|
|
49
|
+
* activate Graph
|
|
50
|
+
* Graph-->>Service: message payload
|
|
51
|
+
* deactivate Graph
|
|
52
|
+
* Service-->>Caller: message payload
|
|
53
|
+
* deactivate Service
|
|
54
|
+
* @memberOf module:integrations/comms/whatsapp/service
|
|
55
|
+
*/
|
|
56
|
+
export class WhatsAppService extends HttpApiService {
|
|
57
|
+
constructor() {
|
|
58
|
+
super(...arguments);
|
|
59
|
+
/**
|
|
60
|
+
* @description The provider name used in error messages
|
|
61
|
+
*/
|
|
62
|
+
this.serviceName = "WhatsApp";
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @description The WhatsApp Cloud API base URL
|
|
66
|
+
* @summary Used when the resolved config carries no `baseUrl`.
|
|
67
|
+
* @returns {string} `"https://graph.facebook.com/v19.0"`.
|
|
68
|
+
*/
|
|
69
|
+
defaultBaseUrl() {
|
|
70
|
+
return "https://graph.facebook.com/v19.0";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* @description Builds the WhatsApp bearer authorization headers
|
|
74
|
+
* @summary Returns `Authorization: Bearer <token>` when configured, and no
|
|
75
|
+
* headers otherwise.
|
|
76
|
+
* @param {WhatsAppServiceConfig} config - The resolved service configuration.
|
|
77
|
+
* @returns {Record<string, string>} The authorization headers (empty without a token).
|
|
78
|
+
*/
|
|
79
|
+
authHeaders(config) {
|
|
80
|
+
return config.token ? { Authorization: `Bearer ${config.token}` } : {};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @description Reads the WhatsApp credentials and defaults from the environment
|
|
84
|
+
* @summary Reads the `comms.whatsApp` slice and returns a partial config
|
|
85
|
+
* when a token or phone number ID is configured, `undefined` otherwise.
|
|
86
|
+
* Values pass through `envString`/`envNumber` to reject unset-leaf proxies.
|
|
87
|
+
* @returns {Partial<WhatsAppServiceConfig> | undefined} A partial config, or `undefined` when neither credential is configured.
|
|
88
|
+
*/
|
|
89
|
+
configFromEnvironment() {
|
|
90
|
+
const env = CommsEnvironment.comms.whatsApp;
|
|
91
|
+
const token = envString(env?.token);
|
|
92
|
+
const phoneNumberId = envString(env?.phoneNumberId);
|
|
93
|
+
if (!token && !phoneNumberId)
|
|
94
|
+
return undefined;
|
|
95
|
+
return {
|
|
96
|
+
token,
|
|
97
|
+
phoneNumberId,
|
|
98
|
+
baseUrl: envString(env.baseUrl),
|
|
99
|
+
timeout: envNumber(env.timeout),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* @description Asserts the access token and sender phone number ID
|
|
104
|
+
* @summary Calls `requireToken()` and returns the configured
|
|
105
|
+
* `phoneNumberId` used to build the messages path.
|
|
106
|
+
* @returns {string} The configured sender phone number ID.
|
|
107
|
+
* @throws {InternalError} When no token or phone number ID is configured.
|
|
108
|
+
*/
|
|
109
|
+
requireTokenAndPhone() {
|
|
110
|
+
this.requireToken();
|
|
111
|
+
const phoneNumberId = this.config.phoneNumberId;
|
|
112
|
+
if (!phoneNumberId) {
|
|
113
|
+
throw new InternalError("WhatsApp requires a phone number id");
|
|
114
|
+
}
|
|
115
|
+
return phoneNumberId;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @description Builds the encoded messages path for a sender
|
|
119
|
+
* @summary Encodes the phone number ID into `/<id>/messages`.
|
|
120
|
+
* @param {string} phoneNumberId - The sender phone number ID.
|
|
121
|
+
* @returns {string} The messages API path.
|
|
122
|
+
*/
|
|
123
|
+
messagesPath(phoneNumberId) {
|
|
124
|
+
return `/${encodeURIComponent(phoneNumberId)}/messages`;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* @description Sends a WhatsApp text message
|
|
128
|
+
* @summary `POST`s a `text` message to the sender's `/messages` endpoint
|
|
129
|
+
* and returns the WhatsApp message payload.
|
|
130
|
+
* @param {WhatsAppTextInput} input - The recipient, text, and preview flag.
|
|
131
|
+
* @returns {Promise<unknown>} The WhatsApp message payload.
|
|
132
|
+
* @throws {InternalError} When credentials or the phone number ID are missing.
|
|
133
|
+
* @throws {BadRequestError} When WhatsApp rejects the message.
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* await whatsapp.sendText({ to: "15551234567", text: "Deployment finished" });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
async sendText(input) {
|
|
140
|
+
const phoneNumberId = this.requireTokenAndPhone();
|
|
141
|
+
try {
|
|
142
|
+
const response = await this.client.post(this.messagesPath(phoneNumberId), {
|
|
143
|
+
messaging_product: "whatsapp",
|
|
144
|
+
recipient_type: "individual",
|
|
145
|
+
to: input.to,
|
|
146
|
+
type: "text",
|
|
147
|
+
text: {
|
|
148
|
+
body: input.text,
|
|
149
|
+
preview_url: input.previewUrl ?? false,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
return response.data;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
throw httpError("WhatsApp", "send text message", error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @description Sends a WhatsApp template message
|
|
160
|
+
* @summary `POST`s a `template` message referencing an approved template
|
|
161
|
+
* name and language, with optional components.
|
|
162
|
+
* @param {WhatsAppTemplateInput} input - The recipient and template definition.
|
|
163
|
+
* @returns {Promise<unknown>} The WhatsApp message payload.
|
|
164
|
+
* @throws {InternalError} When credentials or the phone number ID are missing.
|
|
165
|
+
* @throws {BadRequestError} When WhatsApp rejects the template message.
|
|
166
|
+
*/
|
|
167
|
+
async sendTemplate(input) {
|
|
168
|
+
const phoneNumberId = this.requireTokenAndPhone();
|
|
169
|
+
try {
|
|
170
|
+
const response = await this.client.post(this.messagesPath(phoneNumberId), {
|
|
171
|
+
messaging_product: "whatsapp",
|
|
172
|
+
to: input.to,
|
|
173
|
+
type: "template",
|
|
174
|
+
template: {
|
|
175
|
+
name: input.templateName,
|
|
176
|
+
language: { code: input.languageCode },
|
|
177
|
+
...(input.components ? { components: input.components } : {}),
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
return response.data;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
throw httpError("WhatsApp", "send template message", error);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* @description Sends a WhatsApp media message
|
|
188
|
+
* @summary `POST`s an `image`/`audio`/`video`/`document` message using
|
|
189
|
+
* either an uploaded `mediaId` or a public `link`, with optional caption and
|
|
190
|
+
* filename.
|
|
191
|
+
* @param {WhatsAppMediaInput} input - The recipient and media reference.
|
|
192
|
+
* @returns {Promise<unknown>} The WhatsApp message payload.
|
|
193
|
+
* @throws {InternalError} When credentials or the phone number ID are missing, or neither `mediaId` nor `link` is provided.
|
|
194
|
+
* @throws {BadRequestError} When WhatsApp rejects the media message.
|
|
195
|
+
*/
|
|
196
|
+
async sendMedia(input) {
|
|
197
|
+
const phoneNumberId = this.requireTokenAndPhone();
|
|
198
|
+
if (!input.mediaId && !input.link) {
|
|
199
|
+
throw new InternalError("WhatsApp media messages require a media id or link");
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const response = await this.client.post(this.messagesPath(phoneNumberId), {
|
|
203
|
+
messaging_product: "whatsapp",
|
|
204
|
+
recipient_type: "individual",
|
|
205
|
+
to: input.to,
|
|
206
|
+
type: input.type,
|
|
207
|
+
[input.type]: {
|
|
208
|
+
...(input.mediaId ? { id: input.mediaId } : { link: input.link }),
|
|
209
|
+
...(input.caption ? { caption: input.caption } : {}),
|
|
210
|
+
...(input.filename ? { filename: input.filename } : {}),
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
return response.data;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
throw httpError("WhatsApp", "send media message", error);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* @description Marks an inbound WhatsApp message as read
|
|
221
|
+
* @summary `POST`s a `read` status for the message to the sender's
|
|
222
|
+
* `/messages` endpoint.
|
|
223
|
+
* @param {WhatsAppReadInput} input - The inbound message ID to acknowledge.
|
|
224
|
+
* @returns {Promise<unknown>} The WhatsApp status payload.
|
|
225
|
+
* @throws {InternalError} When credentials, the phone number ID, or the message ID are missing.
|
|
226
|
+
* @throws {BadRequestError} When WhatsApp rejects the request.
|
|
227
|
+
*/
|
|
228
|
+
async markAsRead(input) {
|
|
229
|
+
const phoneNumberId = this.requireTokenAndPhone();
|
|
230
|
+
if (!input.messageId) {
|
|
231
|
+
throw new InternalError("WhatsApp requires a message id");
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
const response = await this.client.post(this.messagesPath(phoneNumberId), {
|
|
235
|
+
messaging_product: "whatsapp",
|
|
236
|
+
status: "read",
|
|
237
|
+
message_id: input.messageId,
|
|
238
|
+
});
|
|
239
|
+
return response.data;
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
throw httpError("WhatsApp", "mark message as read", error);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* @description Fetches WhatsApp media metadata
|
|
247
|
+
* @summary `GET`s the media descriptor (URL, MIME type, size) by media ID;
|
|
248
|
+
* the descriptor's URL is then used to download the binary.
|
|
249
|
+
* @param {string} mediaId - The WhatsApp media ID.
|
|
250
|
+
* @returns {Promise<unknown>} The media metadata payload.
|
|
251
|
+
* @throws {InternalError} When no token is configured or the media ID is empty.
|
|
252
|
+
* @throws {NotFoundError} When the media does not exist (HTTP 404).
|
|
253
|
+
* @throws {BadRequestError} When WhatsApp rejects the request.
|
|
254
|
+
*/
|
|
255
|
+
async getMedia(mediaId) {
|
|
256
|
+
this.requireToken();
|
|
257
|
+
if (!mediaId) {
|
|
258
|
+
throw new InternalError("WhatsApp requires a media id");
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const response = await this.client.get(`/${encodeURIComponent(mediaId)}`);
|
|
262
|
+
return response.data;
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
throw httpError("WhatsApp", "get media", error);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=WhatsAppService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WhatsAppService.js","sourceRoot":"","sources":["../../../../src/comms/whatsapp/WhatsAppService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/comms/whatsapp/index.ts"],"names":[],"mappings":"AAAA,qCAAkC"}
|
package/lib/esm/index.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
export * from "./utils.js";
|
|
7
7
|
export * from "./namespaces/index.js";
|
|
8
8
|
export * from "./feature-flags/index.js";
|
|
9
|
-
export const VERSION = "0.
|
|
10
|
-
export const COMMIT = "
|
|
11
|
-
export const FULL_VERSION = "0.
|
|
9
|
+
export const VERSION = "0.13.0";
|
|
10
|
+
export const COMMIT = "91b0244";
|
|
11
|
+
export const FULL_VERSION = "0.13.0-91b0244";
|
|
12
12
|
export const PACKAGE_NAME = "@decaf-ts/integrations";
|
|
13
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/io/confluence/service
|
|
3
|
+
* @summary Confluence REST API integration service for spaces and pages.
|
|
4
|
+
* @description Exposes Confluence content operations (spaces, pages, and CQL
|
|
5
|
+
* search) as an undecorated client-based service built on
|
|
6
|
+
* {@link HttpApiService}. Configuration comes from an explicit
|
|
7
|
+
* `ConfluenceServiceConfig` or the `io.confluence` environment slice. When both
|
|
8
|
+
* `username` and `token` are configured the service sends HTTP Basic
|
|
9
|
+
* authentication (API token as the password); otherwise the token is sent as a
|
|
10
|
+
* bearer token. The site `baseUrl` is required. Credentials are referenced from
|
|
11
|
+
* configuration (and, from as-graph nodes, from the resolved `confluence`
|
|
12
|
+
* credential secret) and are never embedded in source. Failures are mapped to
|
|
13
|
+
* decaf errors via {@link httpError}.
|
|
14
|
+
*/
|
|
15
|
+
import { InternalError } from "@decaf-ts/db-decorators";
|
|
16
|
+
import { IoEnvironment } from "./../environment.js";
|
|
17
|
+
import { envNumber, envString } from "./../../shared/environmentValue.js";
|
|
18
|
+
import { HttpApiService, httpError, } from "./../../shared/http/index.js";
|
|
19
|
+
/** Default Confluence content type written by the service (`"page"`). */
|
|
20
|
+
const DEFAULT_PAGE_TYPE = "page";
|
|
21
|
+
/**
|
|
22
|
+
* @description Confluence REST API integration service
|
|
23
|
+
* @summary An undecorated HTTP service for reading, creating, updating, and
|
|
24
|
+
* deleting pages, listing spaces, and running CQL searches. The site base URL
|
|
25
|
+
* and API token are required; supplying a `username` switches authentication to
|
|
26
|
+
* Basic, and transport failures are mapped to decaf errors via
|
|
27
|
+
* {@link httpError}.
|
|
28
|
+
* @class ConfluenceService
|
|
29
|
+
* @extends HttpApiService
|
|
30
|
+
* @category IO
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { ConfluenceService } from "@decaf-ts/integrations/io/confluence";
|
|
34
|
+
*
|
|
35
|
+
* const confluence = new ConfluenceService();
|
|
36
|
+
* await confluence.initialize({
|
|
37
|
+
* baseUrl: "https://example.atlassian.net/wiki",
|
|
38
|
+
* username: process.env.CONFLUENCE_USERNAME,
|
|
39
|
+
* token: process.env.GRAPH_CREDENTIAL_CONFLUENCE_TOKEN,
|
|
40
|
+
* });
|
|
41
|
+
* const page = await confluence.getPage("123456");
|
|
42
|
+
* ```
|
|
43
|
+
* @mermaid
|
|
44
|
+
* sequenceDiagram
|
|
45
|
+
* autonumber
|
|
46
|
+
* participant Caller
|
|
47
|
+
* participant Service as ConfluenceService
|
|
48
|
+
* participant API as Confluence REST API
|
|
49
|
+
* Caller->>Service: updatePage(input)
|
|
50
|
+
* activate Service
|
|
51
|
+
* Service->>Service: requireCredentials()
|
|
52
|
+
* opt version omitted
|
|
53
|
+
* Service->>API: GET /rest/api/content/{id}?expand=version
|
|
54
|
+
* activate API
|
|
55
|
+
* API-->>Service: current version
|
|
56
|
+
* deactivate API
|
|
57
|
+
* end
|
|
58
|
+
* Service->>API: PUT /rest/api/content/{id}
|
|
59
|
+
* activate API
|
|
60
|
+
* API-->>Service: updated page
|
|
61
|
+
* deactivate API
|
|
62
|
+
* Service-->>Caller: updated page
|
|
63
|
+
* deactivate Service
|
|
64
|
+
* @memberOf module:integrations/io/confluence/service
|
|
65
|
+
*/
|
|
66
|
+
export class ConfluenceService extends HttpApiService {
|
|
67
|
+
constructor() {
|
|
68
|
+
super(...arguments);
|
|
69
|
+
/**
|
|
70
|
+
* @description The provider name used in error messages
|
|
71
|
+
*/
|
|
72
|
+
this.serviceName = "Confluence";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @description The default base URL for Confluence
|
|
76
|
+
* @summary Returns an empty string; Confluence is site-hosted, so the
|
|
77
|
+
* resolved `baseUrl` (from config or `io.confluence.baseUrl`) is required.
|
|
78
|
+
* @returns {string} An empty string.
|
|
79
|
+
*/
|
|
80
|
+
defaultBaseUrl() {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @description Builds the Confluence authentication headers
|
|
85
|
+
* @summary Uses HTTP Basic (`username:token`) when both values are present,
|
|
86
|
+
* otherwise a bearer token when only `token` is present, otherwise no
|
|
87
|
+
* headers.
|
|
88
|
+
* @param {ConfluenceServiceConfig} config - The resolved service configuration.
|
|
89
|
+
* @returns {Record<string, string>} The authorization headers.
|
|
90
|
+
*/
|
|
91
|
+
authHeaders(config) {
|
|
92
|
+
if (config.username && config.token) {
|
|
93
|
+
const encoded = Buffer.from(`${config.username}:${config.token}`, "utf8").toString("base64");
|
|
94
|
+
return { Authorization: `Basic ${encoded}` };
|
|
95
|
+
}
|
|
96
|
+
return config.token ? { Authorization: `Bearer ${config.token}` } : {};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @description Reads the Confluence credentials and defaults from the environment
|
|
100
|
+
* @summary Reads the `io.confluence` slice and returns a partial config when
|
|
101
|
+
* an API token is configured, `undefined` otherwise. Values pass through
|
|
102
|
+
* `envString`/`envNumber` to reject unset-leaf proxies.
|
|
103
|
+
* @returns {Partial<ConfluenceServiceConfig> | undefined} A partial config, or `undefined` when no Confluence token is configured.
|
|
104
|
+
*/
|
|
105
|
+
configFromEnvironment() {
|
|
106
|
+
const env = IoEnvironment.io.confluence;
|
|
107
|
+
const token = envString(env?.token);
|
|
108
|
+
if (!token)
|
|
109
|
+
return undefined;
|
|
110
|
+
return {
|
|
111
|
+
token,
|
|
112
|
+
username: envString(env.username),
|
|
113
|
+
baseUrl: envString(env.baseUrl),
|
|
114
|
+
timeout: envNumber(env.timeout),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @description Asserts that the Confluence token and site base URL are configured
|
|
119
|
+
* @summary Called by every operation before it touches the network.
|
|
120
|
+
* @returns {void}
|
|
121
|
+
* @throws {InternalError} When no API token or base URL is configured.
|
|
122
|
+
*/
|
|
123
|
+
requireCredentials() {
|
|
124
|
+
if (!this.config.token) {
|
|
125
|
+
throw new InternalError("Confluence requires an API token");
|
|
126
|
+
}
|
|
127
|
+
if (!this.config.baseUrl) {
|
|
128
|
+
throw new InternalError("Confluence requires a base URL");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* @description Wraps a body in the Confluence storage representation
|
|
133
|
+
* @summary Produces the `{ storage: { value, representation } }` envelope
|
|
134
|
+
* the content API expects.
|
|
135
|
+
* @param {string} body - The Confluence storage-format body.
|
|
136
|
+
* @returns {Record<string, unknown>} The storage body envelope.
|
|
137
|
+
*/
|
|
138
|
+
storageBody(body) {
|
|
139
|
+
return {
|
|
140
|
+
storage: {
|
|
141
|
+
value: body,
|
|
142
|
+
representation: "storage",
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @description Fetches a Confluence page
|
|
148
|
+
* @summary `GET`s `/rest/api/content/<id>` with the requested `expand`
|
|
149
|
+
* fields (default `body.storage,version`).
|
|
150
|
+
* @param {string} pageId - The page ID.
|
|
151
|
+
* @param {string} [expand] - Comma-separated fields to expand; defaults to `"body.storage,version"`.
|
|
152
|
+
* @returns {Promise<unknown>} The page payload.
|
|
153
|
+
* @throws {InternalError} When credentials are missing or the page ID is empty.
|
|
154
|
+
* @throws {NotFoundError} When the page does not exist (HTTP 404).
|
|
155
|
+
* @throws {BadRequestError} When the API rejects the request.
|
|
156
|
+
*/
|
|
157
|
+
async getPage(pageId, expand = "body.storage,version") {
|
|
158
|
+
this.requireCredentials();
|
|
159
|
+
if (!pageId) {
|
|
160
|
+
throw new InternalError("Confluence requires a page id");
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const response = await this.client.get(`/rest/api/content/${encodeURIComponent(pageId)}`, { params: { expand } });
|
|
164
|
+
return response.data;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
throw httpError("Confluence", "get page", error);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @description Lists Confluence spaces
|
|
172
|
+
* @summary `GET`s `/rest/api/space` with a result `limit` (default `25`).
|
|
173
|
+
* @param {number} [limit] - Maximum number of spaces to return; defaults to `25`.
|
|
174
|
+
* @returns {Promise<unknown>} The space collection payload.
|
|
175
|
+
* @throws {InternalError} When credentials are missing.
|
|
176
|
+
* @throws {BadRequestError} When the API rejects the request.
|
|
177
|
+
*/
|
|
178
|
+
async listSpaces(limit = 25) {
|
|
179
|
+
this.requireCredentials();
|
|
180
|
+
try {
|
|
181
|
+
const response = await this.client.get("/rest/api/space", {
|
|
182
|
+
params: { limit },
|
|
183
|
+
});
|
|
184
|
+
return response.data;
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
throw httpError("Confluence", "list spaces", error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* @description Creates a Confluence page
|
|
192
|
+
* @summary `POST`s a `page` content entry in the target space, optionally
|
|
193
|
+
* under a parent, with the body in storage format.
|
|
194
|
+
* @param {ConfluencePageInput} input - The space, title, body, and optional parent.
|
|
195
|
+
* @returns {Promise<unknown>} The created page payload.
|
|
196
|
+
* @throws {InternalError} When credentials are missing, or the space key or title is empty.
|
|
197
|
+
* @throws {BadRequestError} When the API rejects the page.
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* await confluence.createPage({
|
|
201
|
+
* spaceKey: "OPS",
|
|
202
|
+
* title: "Release 1.2.0",
|
|
203
|
+
* body: "<p>Details…</p>",
|
|
204
|
+
* });
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
async createPage(input) {
|
|
208
|
+
this.requireCredentials();
|
|
209
|
+
if (!input.spaceKey || !input.title) {
|
|
210
|
+
throw new InternalError("Confluence createPage requires a space key and title");
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const response = await this.client.post("/rest/api/content", {
|
|
214
|
+
type: DEFAULT_PAGE_TYPE,
|
|
215
|
+
title: input.title,
|
|
216
|
+
space: { key: input.spaceKey },
|
|
217
|
+
...(input.parentId ? { ancestors: [{ id: input.parentId }] } : {}),
|
|
218
|
+
body: this.storageBody(input.body ?? ""),
|
|
219
|
+
});
|
|
220
|
+
return response.data;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
throw httpError("Confluence", "create page", error);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* @description Updates a Confluence page
|
|
228
|
+
* @summary `PUT`s the new title and storage body. When `version` is omitted
|
|
229
|
+
* the current version is read first and the next number is submitted, as
|
|
230
|
+
* Confluence requires optimistic versioning.
|
|
231
|
+
* @param {ConfluencePageUpdate} input - The page, new title/body, and optional version.
|
|
232
|
+
* @returns {Promise<unknown>} The updated page payload.
|
|
233
|
+
* @throws {InternalError} When credentials are missing, or the page ID or title is empty.
|
|
234
|
+
* @throws {NotFoundError} When the page does not exist (HTTP 404).
|
|
235
|
+
* @throws {ConflictError} When the submitted version is stale (HTTP 409).
|
|
236
|
+
* @throws {BadRequestError} When the API rejects the update.
|
|
237
|
+
*/
|
|
238
|
+
async updatePage(input) {
|
|
239
|
+
this.requireCredentials();
|
|
240
|
+
if (!input.pageId || !input.title) {
|
|
241
|
+
throw new InternalError("Confluence updatePage requires a page id and title");
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
let version = input.version;
|
|
245
|
+
if (version === undefined) {
|
|
246
|
+
const current = await this.client.get(`/rest/api/content/${encodeURIComponent(input.pageId)}`, { params: { expand: "version" } });
|
|
247
|
+
version = (current.data.version?.number ?? 0) + 1;
|
|
248
|
+
}
|
|
249
|
+
const response = await this.client.put(`/rest/api/content/${encodeURIComponent(input.pageId)}`, {
|
|
250
|
+
id: input.pageId,
|
|
251
|
+
type: DEFAULT_PAGE_TYPE,
|
|
252
|
+
title: input.title,
|
|
253
|
+
version: { number: version },
|
|
254
|
+
body: this.storageBody(input.body ?? ""),
|
|
255
|
+
});
|
|
256
|
+
return response.data;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
throw httpError("Confluence", "update page", error);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* @description Deletes a Confluence page
|
|
264
|
+
* @summary `DELETE`s the content entry and returns `{ deleted: true, pageId }`.
|
|
265
|
+
* @param {string} pageId - The page ID to delete.
|
|
266
|
+
* @returns {Promise<unknown>} `{ deleted: true, pageId }` on success.
|
|
267
|
+
* @throws {InternalError} When credentials are missing or the page ID is empty.
|
|
268
|
+
* @throws {NotFoundError} When the page does not exist (HTTP 404).
|
|
269
|
+
* @throws {BadRequestError} When the API rejects the deletion.
|
|
270
|
+
*/
|
|
271
|
+
async deletePage(pageId) {
|
|
272
|
+
this.requireCredentials();
|
|
273
|
+
if (!pageId) {
|
|
274
|
+
throw new InternalError("Confluence requires a page id");
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
await this.client.delete(`/rest/api/content/${encodeURIComponent(pageId)}`);
|
|
278
|
+
return { deleted: true, pageId };
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
throw httpError("Confluence", "delete page", error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* @description Searches Confluence content with CQL
|
|
286
|
+
* @summary `GET`s `/rest/api/content/search` with the CQL expression and an
|
|
287
|
+
* optional `limit`.
|
|
288
|
+
* @param {ConfluenceSearchInput} input - The CQL query and result limit.
|
|
289
|
+
* @returns {Promise<unknown>} The search result payload.
|
|
290
|
+
* @throws {InternalError} When credentials are missing or the CQL query is empty.
|
|
291
|
+
* @throws {BadRequestError} When the CQL query is invalid.
|
|
292
|
+
*/
|
|
293
|
+
async search(input) {
|
|
294
|
+
this.requireCredentials();
|
|
295
|
+
if (!input.cql) {
|
|
296
|
+
throw new InternalError("Confluence search requires a CQL query");
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
const response = await this.client.get("/rest/api/content/search", {
|
|
300
|
+
params: {
|
|
301
|
+
cql: input.cql,
|
|
302
|
+
...(input.limit !== undefined ? { limit: input.limit } : {}),
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
return response.data;
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
throw httpError("Confluence", "search content", error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=ConfluenceService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfluenceService.js","sourceRoot":"","sources":["../../../../src/io/confluence/ConfluenceService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/io/confluence/index.ts"],"names":[],"mappings":"AAAA,uCAAoC"}
|
|
@@ -37,6 +37,34 @@ export const IoEnvironment = LoggedEnvironment.accumulate({
|
|
|
37
37
|
token: "",
|
|
38
38
|
timeout: undefined,
|
|
39
39
|
},
|
|
40
|
+
microsoftExcel: {
|
|
41
|
+
token: "",
|
|
42
|
+
baseUrl: "",
|
|
43
|
+
timeout: undefined,
|
|
44
|
+
},
|
|
45
|
+
confluence: {
|
|
46
|
+
username: "",
|
|
47
|
+
token: "",
|
|
48
|
+
baseUrl: "",
|
|
49
|
+
timeout: undefined,
|
|
50
|
+
},
|
|
51
|
+
jira: {
|
|
52
|
+
username: "",
|
|
53
|
+
token: "",
|
|
54
|
+
baseUrl: "",
|
|
55
|
+
timeout: undefined,
|
|
56
|
+
},
|
|
57
|
+
googleDocs: {
|
|
58
|
+
token: "",
|
|
59
|
+
apiKey: "",
|
|
60
|
+
baseUrl: "",
|
|
61
|
+
timeout: undefined,
|
|
62
|
+
},
|
|
63
|
+
microsoftSharePoint: {
|
|
64
|
+
token: "",
|
|
65
|
+
baseUrl: "",
|
|
66
|
+
timeout: undefined,
|
|
67
|
+
},
|
|
40
68
|
},
|
|
41
69
|
});
|
|
42
70
|
//# sourceMappingURL=environment.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/io/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/io/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAsFtD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC,UAAU,CAAC;IACxD,EAAE,EAAE;QACF,QAAQ,EAAE;YACR,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,SAA8B;SACxC;QACD,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;QACD,OAAO,EAAE;YACP,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,SAA8B;SACxC;QACD,cAAc,EAAE;YACd,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;QACD,UAAU,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;QACD,UAAU,EAAE;YACV,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;QACD,mBAAmB,EAAE;YACnB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,SAA8B;SACxC;KACF;CACoB,CAAC,CAAC"}
|