digital-tools 2.0.2 → 2.1.1
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/CHANGELOG.md +17 -0
- package/package.json +3 -4
- package/src/define.js +267 -0
- package/src/entities/advertising.js +999 -0
- package/src/entities/ai.js +756 -0
- package/src/entities/analytics.js +1588 -0
- package/src/entities/automation.js +601 -0
- package/src/entities/communication.js +1150 -0
- package/src/entities/crm.js +1386 -0
- package/src/entities/design.js +546 -0
- package/src/entities/development.js +2212 -0
- package/src/entities/document.js +874 -0
- package/src/entities/ecommerce.js +1429 -0
- package/src/entities/experiment.js +1039 -0
- package/src/entities/finance.js +3478 -0
- package/src/entities/forms.js +1892 -0
- package/src/entities/hr.js +661 -0
- package/src/entities/identity.js +997 -0
- package/src/entities/index.js +282 -0
- package/src/entities/infrastructure.js +1153 -0
- package/src/entities/knowledge.js +1438 -0
- package/src/entities/marketing.js +1610 -0
- package/src/entities/media.js +1634 -0
- package/src/entities/notification.js +1199 -0
- package/src/entities/presentation.js +1274 -0
- package/src/entities/productivity.js +1317 -0
- package/src/entities/project-management.js +1136 -0
- package/src/entities/recruiting.js +736 -0
- package/src/entities/shipping.js +509 -0
- package/src/entities/signature.js +1102 -0
- package/src/entities/site.js +222 -0
- package/src/entities/spreadsheet.js +1341 -0
- package/src/entities/storage.js +1198 -0
- package/src/entities/support.js +1166 -0
- package/src/entities/video-conferencing.js +1750 -0
- package/src/entities/video.js +950 -0
- package/src/entities.js +1663 -0
- package/src/index.js +74 -0
- package/src/providers/analytics/index.js +17 -0
- package/src/providers/analytics/mixpanel.js +255 -0
- package/src/providers/calendar/cal-com.js +303 -0
- package/src/providers/calendar/google-calendar.js +335 -0
- package/src/providers/calendar/index.js +20 -0
- package/src/providers/crm/hubspot.js +566 -0
- package/src/providers/crm/index.js +17 -0
- package/src/providers/development/github.js +472 -0
- package/src/providers/development/index.js +17 -0
- package/src/providers/ecommerce/index.js +17 -0
- package/src/providers/ecommerce/shopify.js +378 -0
- package/src/providers/email/index.js +20 -0
- package/src/providers/email/resend.js +258 -0
- package/src/providers/email/sendgrid.js +161 -0
- package/src/providers/finance/index.js +17 -0
- package/src/providers/finance/stripe.js +549 -0
- package/src/providers/forms/index.js +17 -0
- package/src/providers/forms/typeform.js +500 -0
- package/src/providers/index.js +123 -0
- package/src/providers/knowledge/index.js +17 -0
- package/src/providers/knowledge/notion.js +389 -0
- package/src/providers/marketing/index.js +17 -0
- package/src/providers/marketing/mailchimp.js +443 -0
- package/src/providers/media/cloudinary.js +318 -0
- package/src/providers/media/index.js +17 -0
- package/src/providers/messaging/index.js +20 -0
- package/src/providers/messaging/slack.js +393 -0
- package/src/providers/messaging/twilio-sms.js +249 -0
- package/src/providers/project-management/index.js +17 -0
- package/src/providers/project-management/linear.js +575 -0
- package/src/providers/registry.js +86 -0
- package/src/providers/spreadsheet/google-sheets.js +375 -0
- package/src/providers/spreadsheet/index.js +20 -0
- package/src/providers/spreadsheet/xlsx.js +423 -0
- package/src/providers/storage/index.js +24 -0
- package/src/providers/storage/s3.js +419 -0
- package/src/providers/support/index.js +17 -0
- package/src/providers/support/zendesk.js +373 -0
- package/src/providers/tasks/index.js +17 -0
- package/src/providers/tasks/todoist.js +286 -0
- package/src/providers/types.js +9 -0
- package/src/providers/video-conferencing/google-meet.js +286 -0
- package/src/providers/video-conferencing/index.js +31 -0
- package/src/providers/video-conferencing/jitsi.js +254 -0
- package/src/providers/video-conferencing/teams.js +270 -0
- package/src/providers/video-conferencing/zoom.js +332 -0
- package/src/registry.js +128 -0
- package/src/tools/communication.js +184 -0
- package/src/tools/data.js +205 -0
- package/src/tools/index.js +11 -0
- package/src/tools/web.js +137 -0
- package/src/types.js +10 -0
- package/test/define.test.js +306 -0
- package/test/registry.test.js +357 -0
- package/test/tools.test.js +363 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Calendar Provider
|
|
3
|
+
*
|
|
4
|
+
* Concrete implementation of CalendarProvider using Google Calendar API v3.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { defineProvider } from '../registry.js';
|
|
9
|
+
const GOOGLE_CALENDAR_API_URL = 'https://www.googleapis.com/calendar/v3';
|
|
10
|
+
/**
|
|
11
|
+
* Google Calendar provider info
|
|
12
|
+
*/
|
|
13
|
+
export const googleCalendarInfo = {
|
|
14
|
+
id: 'calendar.google-calendar',
|
|
15
|
+
name: 'Google Calendar',
|
|
16
|
+
description: 'Google Calendar API for managing calendars and events',
|
|
17
|
+
category: 'calendar',
|
|
18
|
+
website: 'https://calendar.google.com',
|
|
19
|
+
docsUrl: 'https://developers.google.com/calendar/api/v3/reference',
|
|
20
|
+
requiredConfig: ['accessToken'],
|
|
21
|
+
optionalConfig: ['calendarId'],
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Create Google Calendar provider
|
|
25
|
+
*/
|
|
26
|
+
export function createGoogleCalendarProvider(config) {
|
|
27
|
+
let accessToken;
|
|
28
|
+
let defaultCalendarId;
|
|
29
|
+
/**
|
|
30
|
+
* Helper to make authenticated API requests
|
|
31
|
+
*/
|
|
32
|
+
async function apiRequest(endpoint, options = {}) {
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch(`${GOOGLE_CALENDAR_API_URL}${endpoint}`, {
|
|
35
|
+
...options,
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${accessToken}`,
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
...options.headers,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (response.ok) {
|
|
43
|
+
const data = (await response.json());
|
|
44
|
+
return { ok: true, status: response.status, data };
|
|
45
|
+
}
|
|
46
|
+
const errorData = await response.json().catch(() => ({}));
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
status: response.status,
|
|
50
|
+
error: errorData?.error?.message || response.statusText,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
status: 0,
|
|
57
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
info: googleCalendarInfo,
|
|
63
|
+
async initialize(cfg) {
|
|
64
|
+
accessToken = cfg.accessToken;
|
|
65
|
+
defaultCalendarId = cfg.calendarId;
|
|
66
|
+
if (!accessToken) {
|
|
67
|
+
throw new Error('Google Calendar access token is required');
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
async healthCheck() {
|
|
71
|
+
const start = Date.now();
|
|
72
|
+
const result = await apiRequest('/users/me/calendarList', { method: 'GET' });
|
|
73
|
+
return {
|
|
74
|
+
healthy: result.ok,
|
|
75
|
+
latencyMs: Date.now() - start,
|
|
76
|
+
message: result.ok ? 'Connected' : result.error || `HTTP ${result.status}`,
|
|
77
|
+
checkedAt: new Date(),
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
async dispose() {
|
|
81
|
+
// No cleanup needed
|
|
82
|
+
},
|
|
83
|
+
async listCalendars(options) {
|
|
84
|
+
const params = new URLSearchParams();
|
|
85
|
+
if (options?.limit)
|
|
86
|
+
params.append('maxResults', String(options.limit));
|
|
87
|
+
if (options?.cursor)
|
|
88
|
+
params.append('pageToken', options.cursor);
|
|
89
|
+
const result = await apiRequest(`/users/me/calendarList?${params}`);
|
|
90
|
+
if (!result.ok || !result.data) {
|
|
91
|
+
return { items: [], hasMore: false };
|
|
92
|
+
}
|
|
93
|
+
const items = result.data.items.map((cal) => ({
|
|
94
|
+
id: cal.id,
|
|
95
|
+
name: cal.summary,
|
|
96
|
+
description: cal.description,
|
|
97
|
+
timeZone: cal.timeZone,
|
|
98
|
+
primary: cal.primary || false,
|
|
99
|
+
accessRole: cal.accessRole,
|
|
100
|
+
}));
|
|
101
|
+
return {
|
|
102
|
+
items,
|
|
103
|
+
hasMore: !!result.data.nextPageToken,
|
|
104
|
+
nextCursor: result.data.nextPageToken,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
async getCalendar(calendarId) {
|
|
108
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}`);
|
|
109
|
+
if (!result.ok || !result.data) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const cal = result.data;
|
|
113
|
+
return {
|
|
114
|
+
id: cal.id,
|
|
115
|
+
name: cal.summary,
|
|
116
|
+
description: cal.description,
|
|
117
|
+
timeZone: cal.timeZone,
|
|
118
|
+
primary: false,
|
|
119
|
+
accessRole: 'owner',
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
async createEvent(calendarId, event) {
|
|
123
|
+
const body = {
|
|
124
|
+
summary: event.summary,
|
|
125
|
+
description: event.description,
|
|
126
|
+
location: event.location,
|
|
127
|
+
start: {
|
|
128
|
+
dateTime: event.start.toISOString(),
|
|
129
|
+
timeZone: 'UTC',
|
|
130
|
+
},
|
|
131
|
+
end: {
|
|
132
|
+
dateTime: event.end.toISOString(),
|
|
133
|
+
timeZone: 'UTC',
|
|
134
|
+
},
|
|
135
|
+
attendees: event.attendees?.map((email) => ({ email })),
|
|
136
|
+
reminders: event.reminders
|
|
137
|
+
? {
|
|
138
|
+
useDefault: false,
|
|
139
|
+
overrides: event.reminders.map((r) => ({ method: r.method, minutes: r.minutes })),
|
|
140
|
+
}
|
|
141
|
+
: { useDefault: true },
|
|
142
|
+
recurrence: event.recurrence,
|
|
143
|
+
conferenceData: event.conferenceData
|
|
144
|
+
? {
|
|
145
|
+
createRequest: {
|
|
146
|
+
requestId: `${Date.now()}-${Math.random()}`,
|
|
147
|
+
conferenceSolutionKey: {
|
|
148
|
+
type: event.conferenceData.type === 'hangoutsMeet' ? 'hangoutsMeet' : 'hangoutsMeet',
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
}
|
|
152
|
+
: undefined,
|
|
153
|
+
};
|
|
154
|
+
const params = event.conferenceData ? '?conferenceDataVersion=1' : '';
|
|
155
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}/events${params}`, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
body: JSON.stringify(body),
|
|
158
|
+
});
|
|
159
|
+
if (!result.ok || !result.data) {
|
|
160
|
+
throw new Error(result.error || 'Failed to create event');
|
|
161
|
+
}
|
|
162
|
+
const evt = result.data;
|
|
163
|
+
return {
|
|
164
|
+
id: evt.id,
|
|
165
|
+
calendarId,
|
|
166
|
+
summary: evt.summary,
|
|
167
|
+
description: evt.description,
|
|
168
|
+
location: evt.location,
|
|
169
|
+
start: new Date(evt.start.dateTime || evt.start.date),
|
|
170
|
+
end: new Date(evt.end.dateTime || evt.end.date),
|
|
171
|
+
attendees: evt.attendees?.map((a) => ({
|
|
172
|
+
email: a.email,
|
|
173
|
+
responseStatus: a.responseStatus,
|
|
174
|
+
})),
|
|
175
|
+
status: evt.status,
|
|
176
|
+
recurringEventId: evt.recurringEventId,
|
|
177
|
+
htmlLink: evt.htmlLink,
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
async getEvent(calendarId, eventId) {
|
|
181
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`);
|
|
182
|
+
if (!result.ok || !result.data) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const evt = result.data;
|
|
186
|
+
return {
|
|
187
|
+
id: evt.id,
|
|
188
|
+
calendarId,
|
|
189
|
+
summary: evt.summary,
|
|
190
|
+
description: evt.description,
|
|
191
|
+
location: evt.location,
|
|
192
|
+
start: new Date(evt.start.dateTime || evt.start.date),
|
|
193
|
+
end: new Date(evt.end.dateTime || evt.end.date),
|
|
194
|
+
attendees: evt.attendees?.map((a) => ({
|
|
195
|
+
email: a.email,
|
|
196
|
+
responseStatus: a.responseStatus,
|
|
197
|
+
})),
|
|
198
|
+
status: evt.status,
|
|
199
|
+
recurringEventId: evt.recurringEventId,
|
|
200
|
+
htmlLink: evt.htmlLink,
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
async updateEvent(calendarId, eventId, updates) {
|
|
204
|
+
const body = {};
|
|
205
|
+
if (updates.summary !== undefined)
|
|
206
|
+
body.summary = updates.summary;
|
|
207
|
+
if (updates.description !== undefined)
|
|
208
|
+
body.description = updates.description;
|
|
209
|
+
if (updates.location !== undefined)
|
|
210
|
+
body.location = updates.location;
|
|
211
|
+
if (updates.start) {
|
|
212
|
+
body.start = {
|
|
213
|
+
dateTime: updates.start.toISOString(),
|
|
214
|
+
timeZone: 'UTC',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (updates.end) {
|
|
218
|
+
body.end = {
|
|
219
|
+
dateTime: updates.end.toISOString(),
|
|
220
|
+
timeZone: 'UTC',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (updates.attendees) {
|
|
224
|
+
body.attendees = updates.attendees.map((email) => ({ email }));
|
|
225
|
+
}
|
|
226
|
+
if (updates.reminders) {
|
|
227
|
+
body.reminders = {
|
|
228
|
+
useDefault: false,
|
|
229
|
+
overrides: updates.reminders.map((r) => ({ method: r.method, minutes: r.minutes })),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (updates.recurrence) {
|
|
233
|
+
body.recurrence = updates.recurrence;
|
|
234
|
+
}
|
|
235
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, {
|
|
236
|
+
method: 'PATCH',
|
|
237
|
+
body: JSON.stringify(body),
|
|
238
|
+
});
|
|
239
|
+
if (!result.ok || !result.data) {
|
|
240
|
+
throw new Error(result.error || 'Failed to update event');
|
|
241
|
+
}
|
|
242
|
+
const evt = result.data;
|
|
243
|
+
return {
|
|
244
|
+
id: evt.id,
|
|
245
|
+
calendarId,
|
|
246
|
+
summary: evt.summary,
|
|
247
|
+
description: evt.description,
|
|
248
|
+
location: evt.location,
|
|
249
|
+
start: new Date(evt.start.dateTime || evt.start.date),
|
|
250
|
+
end: new Date(evt.end.dateTime || evt.end.date),
|
|
251
|
+
attendees: evt.attendees?.map((a) => ({
|
|
252
|
+
email: a.email,
|
|
253
|
+
responseStatus: a.responseStatus,
|
|
254
|
+
})),
|
|
255
|
+
status: evt.status,
|
|
256
|
+
recurringEventId: evt.recurringEventId,
|
|
257
|
+
htmlLink: evt.htmlLink,
|
|
258
|
+
};
|
|
259
|
+
},
|
|
260
|
+
async deleteEvent(calendarId, eventId) {
|
|
261
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`, {
|
|
262
|
+
method: 'DELETE',
|
|
263
|
+
});
|
|
264
|
+
return result.ok;
|
|
265
|
+
},
|
|
266
|
+
async listEvents(calendarId, options) {
|
|
267
|
+
const params = new URLSearchParams();
|
|
268
|
+
if (options?.limit)
|
|
269
|
+
params.append('maxResults', String(options.limit));
|
|
270
|
+
if (options?.cursor)
|
|
271
|
+
params.append('pageToken', options.cursor);
|
|
272
|
+
if (options?.timeMin)
|
|
273
|
+
params.append('timeMin', options.timeMin.toISOString());
|
|
274
|
+
if (options?.timeMax)
|
|
275
|
+
params.append('timeMax', options.timeMax.toISOString());
|
|
276
|
+
if (options?.singleEvents !== undefined)
|
|
277
|
+
params.append('singleEvents', String(options.singleEvents));
|
|
278
|
+
if (options?.orderBy)
|
|
279
|
+
params.append('orderBy', options.orderBy);
|
|
280
|
+
const result = await apiRequest(`/calendars/${encodeURIComponent(calendarId)}/events?${params}`);
|
|
281
|
+
if (!result.ok || !result.data) {
|
|
282
|
+
return { items: [], hasMore: false };
|
|
283
|
+
}
|
|
284
|
+
const items = result.data.items.map((evt) => ({
|
|
285
|
+
id: evt.id,
|
|
286
|
+
calendarId,
|
|
287
|
+
summary: evt.summary,
|
|
288
|
+
description: evt.description,
|
|
289
|
+
location: evt.location,
|
|
290
|
+
start: new Date(evt.start.dateTime || evt.start.date),
|
|
291
|
+
end: new Date(evt.end.dateTime || evt.end.date),
|
|
292
|
+
attendees: evt.attendees?.map((a) => ({
|
|
293
|
+
email: a.email,
|
|
294
|
+
responseStatus: a.responseStatus,
|
|
295
|
+
})),
|
|
296
|
+
status: evt.status,
|
|
297
|
+
recurringEventId: evt.recurringEventId,
|
|
298
|
+
htmlLink: evt.htmlLink,
|
|
299
|
+
}));
|
|
300
|
+
return {
|
|
301
|
+
items,
|
|
302
|
+
hasMore: !!result.data.nextPageToken,
|
|
303
|
+
nextCursor: result.data.nextPageToken,
|
|
304
|
+
};
|
|
305
|
+
},
|
|
306
|
+
async findAvailability(calendarIds, timeMin, timeMax) {
|
|
307
|
+
const body = {
|
|
308
|
+
timeMin: timeMin.toISOString(),
|
|
309
|
+
timeMax: timeMax.toISOString(),
|
|
310
|
+
items: calendarIds.map((id) => ({ id })),
|
|
311
|
+
};
|
|
312
|
+
const result = await apiRequest('/freeBusy', {
|
|
313
|
+
method: 'POST',
|
|
314
|
+
body: JSON.stringify(body),
|
|
315
|
+
});
|
|
316
|
+
if (!result.ok || !result.data) {
|
|
317
|
+
return [];
|
|
318
|
+
}
|
|
319
|
+
return calendarIds.map((calendarId) => {
|
|
320
|
+
const calendar = result.data.calendars[calendarId];
|
|
321
|
+
return {
|
|
322
|
+
calendarId,
|
|
323
|
+
busy: calendar?.busy?.map((slot) => ({
|
|
324
|
+
start: new Date(slot.start),
|
|
325
|
+
end: new Date(slot.end),
|
|
326
|
+
})) || [],
|
|
327
|
+
};
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Google Calendar provider definition
|
|
334
|
+
*/
|
|
335
|
+
export const googleCalendarProvider = defineProvider(googleCalendarInfo, async (config) => createGoogleCalendarProvider(config));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar Providers
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
export { googleCalendarInfo, googleCalendarProvider, createGoogleCalendarProvider } from './google-calendar.js';
|
|
7
|
+
export { calComInfo, calComProvider, createCalComProvider } from './cal-com.js';
|
|
8
|
+
import { googleCalendarProvider } from './google-calendar.js';
|
|
9
|
+
import { calComProvider } from './cal-com.js';
|
|
10
|
+
/**
|
|
11
|
+
* Register all calendar providers
|
|
12
|
+
*/
|
|
13
|
+
export function registerCalendarProviders() {
|
|
14
|
+
googleCalendarProvider.register();
|
|
15
|
+
calComProvider.register();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* All calendar providers
|
|
19
|
+
*/
|
|
20
|
+
export const calendarProviders = [googleCalendarProvider, calComProvider];
|