crewly 1.20.264 → 1.20.265
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/config/skills/agent/core/docs-comment/SKILL.md +6 -3
- package/config/skills/agent/core/docs-comment/execute.sh +1 -1
- package/config/skills/agent/core/gmail-send/SKILL.md +4 -0
- package/config/skills/agent/core/gmail-send/execute.sh +1 -1
- package/config/skills/agent/core/gmail-send/execute.test.sh +11 -0
- package/dist/backend/backend/src/constants.d.ts +21 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +21 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts +12 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.js +28 -10
- package/dist/backend/backend/src/controllers/google/google-connect-card.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts +26 -2
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +123 -33
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +10 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.js +4 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.d.ts +16 -0
- package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.js +44 -0
- package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts +159 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js +283 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts +71 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.js +132 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts +28 -10
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js +24 -11
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +3 -1
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +21 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +21 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.js +3 -1
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import { GOOGLE_PRODUCTS } from '../../constants.js';
|
|
|
14
14
|
import { LoggerService } from '../../services/core/logger.service.js';
|
|
15
15
|
const logger = LoggerService.getInstance().createComponentLogger('GoogleConnectCard');
|
|
16
16
|
/** Human names for the products, for the card's first line. */
|
|
17
|
-
const PRODUCT_LABELS = {
|
|
17
|
+
export const PRODUCT_LABELS = {
|
|
18
18
|
gmail: 'Gmail',
|
|
19
19
|
calendar: 'Google Calendar',
|
|
20
20
|
drive: 'Google Drive',
|
|
@@ -22,14 +22,39 @@ const PRODUCT_LABELS = {
|
|
|
22
22
|
/**
|
|
23
23
|
* Build the card. Pure, so the wording is testable without Slack.
|
|
24
24
|
*
|
|
25
|
+
* A reconnect (`reconnect`) replaces the generic "Needs access" with the
|
|
26
|
+
* reason the harness hit — "Gmail needs re-authorization to save drafts" —
|
|
27
|
+
* and names the Google account, because an owner with two Gmail logins has
|
|
28
|
+
* to know which one to pick.
|
|
29
|
+
*
|
|
25
30
|
* @param product - Product needing consent
|
|
26
31
|
* @param url - The ticket link behind the button
|
|
27
32
|
* @param expiresAt - When the link stops working
|
|
33
|
+
* @param reconnect - Why a working connection needs the owner again, and for which account
|
|
28
34
|
* @returns Block Kit blocks and the fallback text
|
|
29
35
|
*/
|
|
30
|
-
export function buildConnectCard(product, url, expiresAt) {
|
|
36
|
+
export function buildConnectCard(product, url, expiresAt, reconnect) {
|
|
31
37
|
const label = PRODUCT_LABELS[product] ?? product;
|
|
32
38
|
const minutes = Math.max(1, Math.round((new Date(expiresAt).getTime() - Date.now()) / 60_000));
|
|
39
|
+
// Say both, because both surprise people: the link dies, and it is for
|
|
40
|
+
// them alone.
|
|
41
|
+
const note = `Only you can see this. The link works once, for about ${minutes} minutes.`;
|
|
42
|
+
if (reconnect) {
|
|
43
|
+
return {
|
|
44
|
+
text: reconnect.message,
|
|
45
|
+
blocks: [
|
|
46
|
+
{
|
|
47
|
+
type: 'section',
|
|
48
|
+
text: { type: 'mrkdwn', text: reconnect.message },
|
|
49
|
+
accessory: { type: 'button', text: { type: 'plain_text', text: 'Reconnect' }, url, style: 'primary' },
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'context',
|
|
53
|
+
elements: [{ type: 'mrkdwn', text: reconnect.account ? `${reconnect.account} · ${note}` : note }],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
33
58
|
return {
|
|
34
59
|
text: `${label} needs access — open the link to authorize Crewly.`,
|
|
35
60
|
blocks: [
|
|
@@ -40,14 +65,7 @@ export function buildConnectCard(product, url, expiresAt) {
|
|
|
40
65
|
},
|
|
41
66
|
{
|
|
42
67
|
type: 'context',
|
|
43
|
-
elements: [
|
|
44
|
-
{
|
|
45
|
-
type: 'mrkdwn',
|
|
46
|
-
// Say both, because both surprise people: the link dies, and it
|
|
47
|
-
// is for them alone.
|
|
48
|
-
text: `Only you can see this. The link works once, for about ${minutes} minutes.`,
|
|
49
|
-
},
|
|
50
|
-
],
|
|
68
|
+
elements: [{ type: 'mrkdwn', text: note }],
|
|
51
69
|
},
|
|
52
70
|
],
|
|
53
71
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-connect-card.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google-connect-card.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAsB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;AAUtF,+DAA+D;AAC/D,MAAM,cAAc,GAA2B;
|
|
1
|
+
{"version":3,"file":"google-connect-card.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google-connect-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,7 @@ import { DocsService } from '../../services/google/docs.service.js';
|
|
|
20
20
|
import { DocsCommentsService } from '../../services/google/docs-comments.service.js';
|
|
21
21
|
import { SheetsService } from '../../services/google/sheets.service.js';
|
|
22
22
|
import { SlidesService } from '../../services/google/slides.service.js';
|
|
23
|
+
import { type ReauthNotifyResult, type ReauthTrigger } from '../../services/google/google-reauth-notifier.service.js';
|
|
23
24
|
/** The services the handlers use; swappable for tests. */
|
|
24
25
|
export interface GoogleControllerDeps {
|
|
25
26
|
tokens: GoogleWorkspaceTokenService;
|
|
@@ -37,16 +38,39 @@ export interface GoogleControllerDeps {
|
|
|
37
38
|
* @param next - Dependency set or null to rebuild lazily
|
|
38
39
|
*/
|
|
39
40
|
export declare function setGoogleControllerDeps(next: GoogleControllerDeps | null): void;
|
|
41
|
+
/**
|
|
42
|
+
* The reconnect a failure calls for, if only the owner can fix it: the grant
|
|
43
|
+
* lacks a scope this call needs (Google 403 insufficient scopes), or Google
|
|
44
|
+
* no longer honours it (expired / revoked — Cloud said `grant_revoked`).
|
|
45
|
+
*
|
|
46
|
+
* @param err - The failure
|
|
47
|
+
* @param req - Incoming request (agent session, Google account)
|
|
48
|
+
* @returns The trigger, or null for any other failure
|
|
49
|
+
*/
|
|
50
|
+
export declare function reauthTriggerFor(err: unknown, req: Request): ReauthTrigger | null;
|
|
51
|
+
/**
|
|
52
|
+
* The agent-facing next step after a reconnect card was (or was not) sent.
|
|
53
|
+
*
|
|
54
|
+
* The agent must not send the owner to the Connections page: the owner is
|
|
55
|
+
* usually on a phone, and the card already is the whole fix.
|
|
56
|
+
*
|
|
57
|
+
* @param trigger - The failure
|
|
58
|
+
* @param result - What the notifier did
|
|
59
|
+
* @returns The hint, or null to fall back to the generic one
|
|
60
|
+
*/
|
|
61
|
+
export declare function reauthHint(trigger: ReauthTrigger, result: ReauthNotifyResult | null): string | null;
|
|
40
62
|
/**
|
|
41
63
|
* Answer a failure with the contract's `{ success:false, error, hint }`
|
|
42
64
|
* shape. `not_connected` carries the consent URL as the hint; the other
|
|
43
|
-
* codes get a one-line next step.
|
|
65
|
+
* codes get a one-line next step. A failure only the owner can fix (missing
|
|
66
|
+
* scope, expired grant) first posts the owner a one-tap reconnect card in
|
|
67
|
+
* Slack, and the hint says so.
|
|
44
68
|
*
|
|
45
69
|
* @param req - Incoming request (for the connect URL)
|
|
46
70
|
* @param res - Response
|
|
47
71
|
* @param err - The failure
|
|
48
72
|
*/
|
|
49
|
-
export declare function sendGoogleError(req: Request, res: Response, err: unknown): void
|
|
73
|
+
export declare function sendGoogleError(req: Request, res: Response, err: unknown): Promise<void>;
|
|
50
74
|
/**
|
|
51
75
|
* GET /api/google/status — `{ connected, cloudConnected, email?, scopes?, grantedAt? }`.
|
|
52
76
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGjD,OAAO,EACL,2BAA2B,EAE5B,MAAM,yDAAyD,CAAC;AAQjE,OAAO,EAAE,YAAY,EAAoC,MAAM,wCAAwC,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAC;AACrF,OAAO,EAAE,aAAa,EAAkB,MAAM,yCAAyC,CAAC;AACxF,OAAO,EAAE,aAAa,EAAqB,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,8 @@ import { SheetsService } from '../../services/google/sheets.service.js';
|
|
|
26
26
|
import { SlidesService } from '../../services/google/slides.service.js';
|
|
27
27
|
import { isOwnerCaller } from '../../middleware/caller-identity.middleware.js';
|
|
28
28
|
import { readAgentSessionHeader } from '../../utils/agent-caller.utils.js';
|
|
29
|
+
import { GoogleReauthNotifier, } from '../../services/google/google-reauth-notifier.service.js';
|
|
30
|
+
import { PRODUCT_LABELS } from './google-connect-card.js';
|
|
29
31
|
/** Who a held send is attributed to when the caller named no agent session. */
|
|
30
32
|
const UNIDENTIFIED_SENDER = 'unidentified caller';
|
|
31
33
|
const logger = LoggerService.getInstance().createComponentLogger('GoogleController');
|
|
@@ -171,22 +173,101 @@ function accountOf(req) {
|
|
|
171
173
|
const raw = typeof req.query.account === 'string' ? req.query.account : req.get('X-Google-Account') ?? '';
|
|
172
174
|
return raw.trim() || undefined;
|
|
173
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* The reconnect a failure calls for, if only the owner can fix it: the grant
|
|
178
|
+
* lacks a scope this call needs (Google 403 insufficient scopes), or Google
|
|
179
|
+
* no longer honours it (expired / revoked — Cloud said `grant_revoked`).
|
|
180
|
+
*
|
|
181
|
+
* @param err - The failure
|
|
182
|
+
* @param req - Incoming request (agent session, Google account)
|
|
183
|
+
* @returns The trigger, or null for any other failure
|
|
184
|
+
*/
|
|
185
|
+
export function reauthTriggerFor(err, req) {
|
|
186
|
+
if (!(err instanceof GoogleWorkspaceError))
|
|
187
|
+
return null;
|
|
188
|
+
const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
|
|
189
|
+
const product = err.details?.product;
|
|
190
|
+
if (!product)
|
|
191
|
+
return null;
|
|
192
|
+
let kind;
|
|
193
|
+
if (err.code === CODES.REAUTH_REQUIRED)
|
|
194
|
+
kind = 'missing_scope';
|
|
195
|
+
else if (err.code === CODES.NOT_CONNECTED && err.details?.reason === 'grant_revoked')
|
|
196
|
+
kind = 'expired';
|
|
197
|
+
else
|
|
198
|
+
return null;
|
|
199
|
+
const account = err.details?.account ?? accountOf(req);
|
|
200
|
+
// Only an agent's call: the owner at the dashboard is already looking at
|
|
201
|
+
// the Connections page, and a card in Slack would be noise.
|
|
202
|
+
const agentSession = isOwnerCaller(req) ? undefined : readAgentSessionHeader(req);
|
|
203
|
+
if (!agentSession)
|
|
204
|
+
return null;
|
|
205
|
+
return { product, kind, agentSession, ...(account ? { account } : {}) };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Ask the owner to reconnect, without holding the skill call for long.
|
|
209
|
+
*
|
|
210
|
+
* @param trigger - The failure
|
|
211
|
+
* @returns What happened, or null when no notifier is wired or it timed out
|
|
212
|
+
*/
|
|
213
|
+
async function notifyReauth(trigger) {
|
|
214
|
+
const notifier = GoogleReauthNotifier.getInstance();
|
|
215
|
+
if (!notifier)
|
|
216
|
+
return null;
|
|
217
|
+
let timer;
|
|
218
|
+
const timeout = new Promise((resolve) => {
|
|
219
|
+
timer = setTimeout(() => resolve(null), GOOGLE_WORKSPACE_CONSTANTS.REAUTH.POST_TIMEOUT_MS);
|
|
220
|
+
});
|
|
221
|
+
try {
|
|
222
|
+
return await Promise.race([notifier.notify(trigger).catch(() => null), timeout]);
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
if (timer)
|
|
226
|
+
clearTimeout(timer);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* The agent-facing next step after a reconnect card was (or was not) sent.
|
|
231
|
+
*
|
|
232
|
+
* The agent must not send the owner to the Connections page: the owner is
|
|
233
|
+
* usually on a phone, and the card already is the whole fix.
|
|
234
|
+
*
|
|
235
|
+
* @param trigger - The failure
|
|
236
|
+
* @param result - What the notifier did
|
|
237
|
+
* @returns The hint, or null to fall back to the generic one
|
|
238
|
+
*/
|
|
239
|
+
export function reauthHint(trigger, result) {
|
|
240
|
+
const label = PRODUCT_LABELS[trigger.product] ?? trigger.product;
|
|
241
|
+
if (result?.status === 'posted') {
|
|
242
|
+
return `A reconnect link was sent to the owner in Slack. Tell them in one line that you need them to tap it (no need to mention Connections). You will get a message saying ${label} is reconnected — then retry.`;
|
|
243
|
+
}
|
|
244
|
+
if (result?.status === 'already_sent') {
|
|
245
|
+
return `A reconnect link was already sent to the owner in Slack at ${result.sentAt}; no new one is sent before ${result.nextCardAfter}. Do not ask again — you will get a message saying ${label} is reconnected, then retry.`;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
174
249
|
/**
|
|
175
250
|
* Answer a failure with the contract's `{ success:false, error, hint }`
|
|
176
251
|
* shape. `not_connected` carries the consent URL as the hint; the other
|
|
177
|
-
* codes get a one-line next step.
|
|
252
|
+
* codes get a one-line next step. A failure only the owner can fix (missing
|
|
253
|
+
* scope, expired grant) first posts the owner a one-tap reconnect card in
|
|
254
|
+
* Slack, and the hint says so.
|
|
178
255
|
*
|
|
179
256
|
* @param req - Incoming request (for the connect URL)
|
|
180
257
|
* @param res - Response
|
|
181
258
|
* @param err - The failure
|
|
182
259
|
*/
|
|
183
|
-
export function sendGoogleError(req, res, err) {
|
|
260
|
+
export async function sendGoogleError(req, res, err) {
|
|
184
261
|
const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
|
|
185
262
|
if (err instanceof GoogleWorkspaceError) {
|
|
263
|
+
const trigger = reauthTriggerFor(err, req);
|
|
264
|
+
const reauth = trigger ? await notifyReauth(trigger) : null;
|
|
265
|
+
const reauthText = trigger ? reauthHint(trigger, reauth) : null;
|
|
186
266
|
let hint;
|
|
187
267
|
switch (err.code) {
|
|
188
268
|
case CODES.NOT_CONNECTED:
|
|
189
|
-
hint =
|
|
269
|
+
hint = reauthText
|
|
270
|
+
?? connectUrlOrNull(req)
|
|
190
271
|
?? 'Sign in to Crewly Cloud (Settings → Cloud & devices), then connect Google Workspace under Connections.';
|
|
191
272
|
break;
|
|
192
273
|
case CODES.NOT_LOGGED_IN:
|
|
@@ -198,10 +279,13 @@ export function sendGoogleError(req, res, err) {
|
|
|
198
279
|
case CODES.VALIDATION:
|
|
199
280
|
hint = 'Fix the request and retry.';
|
|
200
281
|
break;
|
|
201
|
-
case CODES.REAUTH_REQUIRED:
|
|
282
|
+
case CODES.REAUTH_REQUIRED: {
|
|
202
283
|
// Owner-away: the only step is one tap on the Slack card.
|
|
203
|
-
|
|
284
|
+
const product = err.details?.product ?? 'drive';
|
|
285
|
+
hint = reauthText
|
|
286
|
+
?? `Ask the owner to reconnect ${PRODUCT_LABELS[product] ?? product}: run the google-connect skill with --product ${product}. It posts a one-tap card in Slack; nothing to do on this machine.`;
|
|
204
287
|
break;
|
|
288
|
+
}
|
|
205
289
|
case PEOPLE_CONSTANTS.NOT_PERMITTED_CODE:
|
|
206
290
|
hint = PEOPLE_CONSTANTS.NOT_PERMITTED_HINT;
|
|
207
291
|
break;
|
|
@@ -210,7 +294,13 @@ export function sendGoogleError(req, res, err) {
|
|
|
210
294
|
? 'The Google token was rejected; retry once — the cache has been cleared.'
|
|
211
295
|
: 'Google or Crewly Cloud failed; retry later.';
|
|
212
296
|
}
|
|
213
|
-
res.status(err.status).json({
|
|
297
|
+
res.status(err.status).json({
|
|
298
|
+
success: false,
|
|
299
|
+
error: err.code,
|
|
300
|
+
message: err.message,
|
|
301
|
+
hint,
|
|
302
|
+
...(reauthText ? { reconnectLinkSent: true } : {}),
|
|
303
|
+
});
|
|
214
304
|
return;
|
|
215
305
|
}
|
|
216
306
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -251,7 +341,7 @@ export async function getStatus(req, res) {
|
|
|
251
341
|
res.json({ success: true, data });
|
|
252
342
|
}
|
|
253
343
|
catch (err) {
|
|
254
|
-
sendGoogleError(req, res, err);
|
|
344
|
+
await sendGoogleError(req, res, err);
|
|
255
345
|
}
|
|
256
346
|
}
|
|
257
347
|
/**
|
|
@@ -267,7 +357,7 @@ export async function getConnectUrl(req, res) {
|
|
|
267
357
|
res.json({ success: true, data: { url } });
|
|
268
358
|
}
|
|
269
359
|
catch (err) {
|
|
270
|
-
sendGoogleError(req, res, err);
|
|
360
|
+
await sendGoogleError(req, res, err);
|
|
271
361
|
}
|
|
272
362
|
}
|
|
273
363
|
/**
|
|
@@ -283,7 +373,7 @@ export async function disconnect(req, res) {
|
|
|
283
373
|
res.json({ success: true, data });
|
|
284
374
|
}
|
|
285
375
|
catch (err) {
|
|
286
|
-
sendGoogleError(req, res, err);
|
|
376
|
+
await sendGoogleError(req, res, err);
|
|
287
377
|
}
|
|
288
378
|
}
|
|
289
379
|
/**
|
|
@@ -305,7 +395,7 @@ export async function setDefaultAccount(req, res) {
|
|
|
305
395
|
res.json({ success: true, data });
|
|
306
396
|
}
|
|
307
397
|
catch (err) {
|
|
308
|
-
sendGoogleError(req, res, err);
|
|
398
|
+
await sendGoogleError(req, res, err);
|
|
309
399
|
}
|
|
310
400
|
}
|
|
311
401
|
/**
|
|
@@ -335,7 +425,7 @@ export async function gmailSearch(req, res) {
|
|
|
335
425
|
res.json({ success: true, data: { query, count: messages.length, messages } });
|
|
336
426
|
}
|
|
337
427
|
catch (err) {
|
|
338
|
-
sendGoogleError(req, res, err);
|
|
428
|
+
await sendGoogleError(req, res, err);
|
|
339
429
|
}
|
|
340
430
|
}
|
|
341
431
|
/**
|
|
@@ -350,7 +440,7 @@ export async function gmailRead(req, res) {
|
|
|
350
440
|
res.json({ success: true, data: message });
|
|
351
441
|
}
|
|
352
442
|
catch (err) {
|
|
353
|
-
sendGoogleError(req, res, err);
|
|
443
|
+
await sendGoogleError(req, res, err);
|
|
354
444
|
}
|
|
355
445
|
}
|
|
356
446
|
/**
|
|
@@ -424,7 +514,7 @@ export async function gmailSend(req, res) {
|
|
|
424
514
|
res.json({ success: true, data: sent });
|
|
425
515
|
}
|
|
426
516
|
catch (err) {
|
|
427
|
-
sendGoogleError(req, res, err);
|
|
517
|
+
await sendGoogleError(req, res, err);
|
|
428
518
|
}
|
|
429
519
|
}
|
|
430
520
|
/**
|
|
@@ -444,7 +534,7 @@ export async function calendarList(req, res) {
|
|
|
444
534
|
res.json({ success: true, data: { count: events.length, events } });
|
|
445
535
|
}
|
|
446
536
|
catch (err) {
|
|
447
|
-
sendGoogleError(req, res, err);
|
|
537
|
+
await sendGoogleError(req, res, err);
|
|
448
538
|
}
|
|
449
539
|
}
|
|
450
540
|
/**
|
|
@@ -474,7 +564,7 @@ export async function calendarCreate(req, res) {
|
|
|
474
564
|
res.json({ success: true, data: event });
|
|
475
565
|
}
|
|
476
566
|
catch (err) {
|
|
477
|
-
sendGoogleError(req, res, err);
|
|
567
|
+
await sendGoogleError(req, res, err);
|
|
478
568
|
}
|
|
479
569
|
}
|
|
480
570
|
// ---------------------------------------------------------------------------
|
|
@@ -497,7 +587,7 @@ export async function driveSearch(req, res) {
|
|
|
497
587
|
res.json({ success: true, data: { count: files.length, files } });
|
|
498
588
|
}
|
|
499
589
|
catch (err) {
|
|
500
|
-
sendGoogleError(req, res, err);
|
|
590
|
+
await sendGoogleError(req, res, err);
|
|
501
591
|
}
|
|
502
592
|
}
|
|
503
593
|
/**
|
|
@@ -511,7 +601,7 @@ export async function driveGet(req, res) {
|
|
|
511
601
|
res.json({ success: true, data: await depsForRequest(req).drive.get(String(req.params.id ?? '')) });
|
|
512
602
|
}
|
|
513
603
|
catch (err) {
|
|
514
|
-
sendGoogleError(req, res, err);
|
|
604
|
+
await sendGoogleError(req, res, err);
|
|
515
605
|
}
|
|
516
606
|
}
|
|
517
607
|
/**
|
|
@@ -525,7 +615,7 @@ export async function driveContent(req, res) {
|
|
|
525
615
|
res.json({ success: true, data: await depsForRequest(req).drive.readContent(String(req.params.id ?? '')) });
|
|
526
616
|
}
|
|
527
617
|
catch (err) {
|
|
528
|
-
sendGoogleError(req, res, err);
|
|
618
|
+
await sendGoogleError(req, res, err);
|
|
529
619
|
}
|
|
530
620
|
}
|
|
531
621
|
/**
|
|
@@ -549,7 +639,7 @@ export async function driveUpload(req, res) {
|
|
|
549
639
|
res.json({ success: true, data: file });
|
|
550
640
|
}
|
|
551
641
|
catch (err) {
|
|
552
|
-
sendGoogleError(req, res, err);
|
|
642
|
+
await sendGoogleError(req, res, err);
|
|
553
643
|
}
|
|
554
644
|
}
|
|
555
645
|
// ---------------------------------------------------------------------------
|
|
@@ -566,7 +656,7 @@ export async function docsRead(req, res) {
|
|
|
566
656
|
res.json({ success: true, data: await depsForRequest(req).docs.read(String(req.params.id ?? '')) });
|
|
567
657
|
}
|
|
568
658
|
catch (err) {
|
|
569
|
-
sendGoogleError(req, res, err);
|
|
659
|
+
await sendGoogleError(req, res, err);
|
|
570
660
|
}
|
|
571
661
|
}
|
|
572
662
|
/**
|
|
@@ -583,7 +673,7 @@ export async function docsCreate(req, res) {
|
|
|
583
673
|
res.json({ success: true, data: doc });
|
|
584
674
|
}
|
|
585
675
|
catch (err) {
|
|
586
|
-
sendGoogleError(req, res, err);
|
|
676
|
+
await sendGoogleError(req, res, err);
|
|
587
677
|
}
|
|
588
678
|
}
|
|
589
679
|
/**
|
|
@@ -598,7 +688,7 @@ export async function docsAppend(req, res) {
|
|
|
598
688
|
res.json({ success: true, data: await depsForRequest(req).docs.append(String(req.params.id ?? ''), String(body.text ?? '')) });
|
|
599
689
|
}
|
|
600
690
|
catch (err) {
|
|
601
|
-
sendGoogleError(req, res, err);
|
|
691
|
+
await sendGoogleError(req, res, err);
|
|
602
692
|
}
|
|
603
693
|
}
|
|
604
694
|
/**
|
|
@@ -614,7 +704,7 @@ export async function docsCommentsList(req, res) {
|
|
|
614
704
|
res.json({ success: true, data: await depsForRequest(req).docComments.list(String(req.params.id ?? ''), { includeResolved }) });
|
|
615
705
|
}
|
|
616
706
|
catch (err) {
|
|
617
|
-
sendGoogleError(req, res, err);
|
|
707
|
+
await sendGoogleError(req, res, err);
|
|
618
708
|
}
|
|
619
709
|
}
|
|
620
710
|
/**
|
|
@@ -632,7 +722,7 @@ export async function docsCommentsAdd(req, res) {
|
|
|
632
722
|
res.json({ success: true, data });
|
|
633
723
|
}
|
|
634
724
|
catch (err) {
|
|
635
|
-
sendGoogleError(req, res, err);
|
|
725
|
+
await sendGoogleError(req, res, err);
|
|
636
726
|
}
|
|
637
727
|
}
|
|
638
728
|
/**
|
|
@@ -649,7 +739,7 @@ export async function docsCommentsReply(req, res) {
|
|
|
649
739
|
res.json({ success: true, data });
|
|
650
740
|
}
|
|
651
741
|
catch (err) {
|
|
652
|
-
sendGoogleError(req, res, err);
|
|
742
|
+
await sendGoogleError(req, res, err);
|
|
653
743
|
}
|
|
654
744
|
}
|
|
655
745
|
/**
|
|
@@ -667,7 +757,7 @@ export async function docsCommentsResolve(req, res) {
|
|
|
667
757
|
res.json({ success: true, data });
|
|
668
758
|
}
|
|
669
759
|
catch (err) {
|
|
670
|
-
sendGoogleError(req, res, err);
|
|
760
|
+
await sendGoogleError(req, res, err);
|
|
671
761
|
}
|
|
672
762
|
}
|
|
673
763
|
// ---------------------------------------------------------------------------
|
|
@@ -684,7 +774,7 @@ export async function sheetsInfo(req, res) {
|
|
|
684
774
|
res.json({ success: true, data: await depsForRequest(req).sheets.info(String(req.params.id ?? '')) });
|
|
685
775
|
}
|
|
686
776
|
catch (err) {
|
|
687
|
-
sendGoogleError(req, res, err);
|
|
777
|
+
await sendGoogleError(req, res, err);
|
|
688
778
|
}
|
|
689
779
|
}
|
|
690
780
|
/**
|
|
@@ -698,7 +788,7 @@ export async function sheetsRead(req, res) {
|
|
|
698
788
|
res.json({ success: true, data: await depsForRequest(req).sheets.read(String(req.params.id ?? ''), q(req, 'range') || undefined) });
|
|
699
789
|
}
|
|
700
790
|
catch (err) {
|
|
701
|
-
sendGoogleError(req, res, err);
|
|
791
|
+
await sendGoogleError(req, res, err);
|
|
702
792
|
}
|
|
703
793
|
}
|
|
704
794
|
/**
|
|
@@ -715,7 +805,7 @@ export async function sheetsCreate(req, res) {
|
|
|
715
805
|
res.json({ success: true, data: info });
|
|
716
806
|
}
|
|
717
807
|
catch (err) {
|
|
718
|
-
sendGoogleError(req, res, err);
|
|
808
|
+
await sendGoogleError(req, res, err);
|
|
719
809
|
}
|
|
720
810
|
}
|
|
721
811
|
/**
|
|
@@ -733,7 +823,7 @@ export async function sheetsWrite(req, res) {
|
|
|
733
823
|
res.json({ success: true, data: { mode: body.mode === 'update' ? 'update' : 'append', ...result } });
|
|
734
824
|
}
|
|
735
825
|
catch (err) {
|
|
736
|
-
sendGoogleError(req, res, err);
|
|
826
|
+
await sendGoogleError(req, res, err);
|
|
737
827
|
}
|
|
738
828
|
}
|
|
739
829
|
// ---------------------------------------------------------------------------
|
|
@@ -750,7 +840,7 @@ export async function slidesRead(req, res) {
|
|
|
750
840
|
res.json({ success: true, data: await depsForRequest(req).slides.read(String(req.params.id ?? '')) });
|
|
751
841
|
}
|
|
752
842
|
catch (err) {
|
|
753
|
-
sendGoogleError(req, res, err);
|
|
843
|
+
await sendGoogleError(req, res, err);
|
|
754
844
|
}
|
|
755
845
|
}
|
|
756
846
|
/**
|
|
@@ -767,7 +857,7 @@ export async function slidesCreate(req, res) {
|
|
|
767
857
|
res.json({ success: true, data: deck });
|
|
768
858
|
}
|
|
769
859
|
catch (err) {
|
|
770
|
-
sendGoogleError(req, res, err);
|
|
860
|
+
await sendGoogleError(req, res, err);
|
|
771
861
|
}
|
|
772
862
|
}
|
|
773
863
|
/**
|
|
@@ -848,7 +938,7 @@ export async function gmailResolveHeld(req, res) {
|
|
|
848
938
|
res.json({ success: true, data: sent });
|
|
849
939
|
}
|
|
850
940
|
catch (err) {
|
|
851
|
-
sendGoogleError(req, res, err);
|
|
941
|
+
await sendGoogleError(req, res, err);
|
|
852
942
|
}
|
|
853
943
|
}
|
|
854
944
|
//# sourceMappingURL=google.controller.js.map
|