crewly 1.20.28 → 1.20.30
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/canva-create/SKILL.md +53 -0
- package/config/skills/agent/core/canva-create/execute.sh +88 -0
- package/config/skills/agent/core/canva-create/execute.test.sh +54 -0
- package/config/skills/agent/core/canva-designs/SKILL.md +51 -0
- package/config/skills/agent/core/canva-designs/execute.sh +96 -0
- package/config/skills/agent/core/canva-designs/execute.test.sh +54 -0
- package/config/skills/agent/core/canva-export/SKILL.md +52 -0
- package/config/skills/agent/core/canva-export/execute.sh +111 -0
- package/config/skills/agent/core/canva-export/execute.test.sh +55 -0
- package/config/skills/agent/core/canva-upload/SKILL.md +49 -0
- package/config/skills/agent/core/canva-upload/execute.sh +72 -0
- package/config/skills/agent/core/canva-upload/execute.test.sh +54 -0
- package/config/skills/agent/core/docs-read/SKILL.md +50 -0
- package/config/skills/agent/core/docs-read/execute.sh +68 -0
- package/config/skills/agent/core/docs-read/execute.test.sh +52 -0
- package/config/skills/agent/core/docs-write/SKILL.md +55 -0
- package/config/skills/agent/core/docs-write/execute.sh +90 -0
- package/config/skills/agent/core/docs-write/execute.test.sh +54 -0
- package/config/skills/agent/core/drive-read/SKILL.md +53 -0
- package/config/skills/agent/core/drive-read/execute.sh +79 -0
- package/config/skills/agent/core/drive-read/execute.test.sh +55 -0
- package/config/skills/agent/core/drive-search/SKILL.md +55 -0
- package/config/skills/agent/core/drive-search/execute.sh +87 -0
- package/config/skills/agent/core/drive-search/execute.test.sh +54 -0
- package/config/skills/agent/core/drive-upload/SKILL.md +54 -0
- package/config/skills/agent/core/drive-upload/execute.sh +117 -0
- package/config/skills/agent/core/drive-upload/execute.test.sh +57 -0
- package/config/skills/agent/core/sheets-read/SKILL.md +53 -0
- package/config/skills/agent/core/sheets-read/execute.sh +81 -0
- package/config/skills/agent/core/sheets-read/execute.test.sh +52 -0
- package/config/skills/agent/core/sheets-write/SKILL.md +56 -0
- package/config/skills/agent/core/sheets-write/execute.sh +103 -0
- package/config/skills/agent/core/sheets-write/execute.test.sh +57 -0
- package/config/skills/agent/core/slides-create/SKILL.md +61 -0
- package/config/skills/agent/core/slides-create/execute.sh +92 -0
- package/config/skills/agent/core/slides-create/execute.test.sh +54 -0
- package/config/skills/agent/core/slides-read/SKILL.md +49 -0
- package/config/skills/agent/core/slides-read/execute.sh +67 -0
- package/config/skills/agent/core/slides-read/execute.test.sh +50 -0
- package/dist/backend/backend/src/constants.d.ts +69 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +73 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts +48 -0
- package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/canva/canva.controller.js +183 -0
- package/dist/backend/backend/src/controllers/canva/canva.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts +22 -0
- package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/canva/canva.routes.js +34 -0
- package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts +100 -0
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +237 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.d.ts +13 -0
- package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js +27 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +3 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts +98 -0
- package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/canva/canva-token.service.js +198 -0
- package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -0
- package/dist/backend/backend/src/services/canva/canva.service.d.ts +184 -0
- package/dist/backend/backend/src/services/canva/canva.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/canva/canva.service.js +274 -0
- package/dist/backend/backend/src/services/canva/canva.service.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +2 -2
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/docs.service.d.ts +117 -0
- package/dist/backend/backend/src/services/google/docs.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/docs.service.js +152 -0
- package/dist/backend/backend/src/services/google/docs.service.js.map +1 -0
- package/dist/backend/backend/src/services/google/drive.service.d.ts +157 -0
- package/dist/backend/backend/src/services/google/drive.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/drive.service.js +203 -0
- package/dist/backend/backend/src/services/google/drive.service.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-api.client.d.ts +15 -7
- 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 +13 -6
- package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
- package/dist/backend/backend/src/services/google/sheets.service.d.ts +118 -0
- package/dist/backend/backend/src/services/google/sheets.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/sheets.service.js +158 -0
- package/dist/backend/backend/src/services/google/sheets.service.js.map +1 -0
- package/dist/backend/backend/src/services/google/slides.service.d.ts +136 -0
- package/dist/backend/backend/src/services/google/slides.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/slides.service.js +153 -0
- package/dist/backend/backend/src/services/google/slides.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +16 -3
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -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 +11 -7
- 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 +69 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +73 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +2 -2
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +16 -3
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -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 +11 -7
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/frontend/dist/assets/{index-d1bd0dec.js → index-96b51cd9.js} +243 -243
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canva controller — `/api/canva/*` on this instance.
|
|
3
|
+
*
|
|
4
|
+
* Grant management goes through Cloud (status / connect-url / disconnect);
|
|
5
|
+
* designs, exports and assets go straight to api.canva.com with the token
|
|
6
|
+
* Cloud mints. Backs the canva-* skills.
|
|
7
|
+
*
|
|
8
|
+
* @module controllers/canva/canva.controller
|
|
9
|
+
*/
|
|
10
|
+
import { CANVA_CONSTANTS } from '../../constants.js';
|
|
11
|
+
import { LoggerService } from '../../services/core/logger.service.js';
|
|
12
|
+
import { CanvaTokenService, CanvaError } from '../../services/canva/canva-token.service.js';
|
|
13
|
+
import { CanvaService } from '../../services/canva/canva.service.js';
|
|
14
|
+
const logger = LoggerService.getInstance().createComponentLogger('CanvaController');
|
|
15
|
+
let deps = null;
|
|
16
|
+
function getDeps() {
|
|
17
|
+
if (!deps) {
|
|
18
|
+
const tokens = CanvaTokenService.getInstance();
|
|
19
|
+
deps = { tokens, canva: new CanvaService({ tokens }) };
|
|
20
|
+
}
|
|
21
|
+
return deps;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Replace the dependency set (tests).
|
|
25
|
+
*
|
|
26
|
+
* @param next - Deps or null to rebuild lazily
|
|
27
|
+
*/
|
|
28
|
+
export function setCanvaControllerDeps(next) {
|
|
29
|
+
deps = next;
|
|
30
|
+
}
|
|
31
|
+
function resolveReturnUrl(req) {
|
|
32
|
+
const explicit = typeof req.query.returnUrl === 'string' ? req.query.returnUrl : '';
|
|
33
|
+
if (/^https?:\/\//i.test(explicit))
|
|
34
|
+
return explicit;
|
|
35
|
+
return `${req.protocol}://${req.get('host')}${CANVA_CONSTANTS.SETTINGS_RETURN_PATH}`;
|
|
36
|
+
}
|
|
37
|
+
function connectUrlOrNull(req) {
|
|
38
|
+
try {
|
|
39
|
+
return getDeps().tokens.buildConnectUrl(resolveReturnUrl(req));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Answer a failure with `{ success:false, error, message, hint }`.
|
|
47
|
+
*
|
|
48
|
+
* @param req - Request (for the connect URL hint)
|
|
49
|
+
* @param res - Response
|
|
50
|
+
* @param err - The failure
|
|
51
|
+
*/
|
|
52
|
+
export function sendCanvaError(req, res, err) {
|
|
53
|
+
const CODES = CANVA_CONSTANTS.ERROR_CODES;
|
|
54
|
+
if (err instanceof CanvaError) {
|
|
55
|
+
let hint;
|
|
56
|
+
switch (err.code) {
|
|
57
|
+
case CODES.NOT_CONNECTED:
|
|
58
|
+
hint = connectUrlOrNull(req) ?? 'Sign in to Crewly Cloud (Settings → Cloud), then connect Canva under Settings → Integrations.';
|
|
59
|
+
break;
|
|
60
|
+
case CODES.NOT_LOGGED_IN:
|
|
61
|
+
hint = 'Sign in to Crewly Cloud first (Settings → Cloud).';
|
|
62
|
+
break;
|
|
63
|
+
case CODES.NOT_CONFIGURED:
|
|
64
|
+
hint = 'Crewly Cloud is not configured for Canva; nothing to do on this instance.';
|
|
65
|
+
break;
|
|
66
|
+
case CODES.VALIDATION:
|
|
67
|
+
hint = 'Fix the request and retry.';
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
hint = err.status === 401 ? 'The Canva token was rejected; retry once — the cache has been cleared.' : 'Canva or Crewly Cloud failed; retry later.';
|
|
71
|
+
}
|
|
72
|
+
res.status(err.status).json({ success: false, error: err.code, message: err.message, hint });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
76
|
+
logger.error('Unexpected Canva failure', { error: message });
|
|
77
|
+
res.status(500).json({ success: false, error: 'internal', message, hint: 'Check the backend log.' });
|
|
78
|
+
}
|
|
79
|
+
function q(req, name) {
|
|
80
|
+
const v = req.query[name];
|
|
81
|
+
return typeof v === 'string' ? v.trim() : '';
|
|
82
|
+
}
|
|
83
|
+
function qInt(req, name) {
|
|
84
|
+
const v = q(req, name);
|
|
85
|
+
return v ? Number.parseInt(v, 10) : undefined;
|
|
86
|
+
}
|
|
87
|
+
/** GET /api/canva/status */
|
|
88
|
+
export async function getStatus(req, res) {
|
|
89
|
+
try {
|
|
90
|
+
res.json({ success: true, data: await getDeps().tokens.status() });
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
sendCanvaError(req, res, err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** GET /api/canva/connect-url — `{ url }` to open in the browser. */
|
|
97
|
+
export async function getConnectUrl(req, res) {
|
|
98
|
+
try {
|
|
99
|
+
res.json({ success: true, data: { url: getDeps().tokens.buildConnectUrl(resolveReturnUrl(req)) } });
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
sendCanvaError(req, res, err);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** DELETE /api/canva/disconnect */
|
|
106
|
+
export async function disconnect(req, res) {
|
|
107
|
+
try {
|
|
108
|
+
res.json({ success: true, data: await getDeps().tokens.disconnect() });
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
sendCanvaError(req, res, err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** GET /api/canva/designs?q=&ownership=&sort=&limit=&continuation= */
|
|
115
|
+
export async function listDesigns(req, res) {
|
|
116
|
+
try {
|
|
117
|
+
const ownership = q(req, 'ownership');
|
|
118
|
+
const sort = q(req, 'sort');
|
|
119
|
+
const out = await getDeps().canva.listDesigns({
|
|
120
|
+
query: q(req, 'q') || undefined,
|
|
121
|
+
ownership: ownership === 'owned' || ownership === 'shared' || ownership === 'any' ? ownership : undefined,
|
|
122
|
+
sortBy: ['relevance', 'modified_descending', 'modified_ascending', 'title_descending', 'title_ascending'].find((s) => s === sort),
|
|
123
|
+
limit: qInt(req, 'limit'),
|
|
124
|
+
continuation: q(req, 'continuation') || undefined,
|
|
125
|
+
});
|
|
126
|
+
res.json({ success: true, data: { count: out.designs.length, designs: out.designs, ...(out.continuation ? { continuation: out.continuation } : {}) } });
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
sendCanvaError(req, res, err);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** GET /api/canva/designs/:id */
|
|
133
|
+
export async function getDesign(req, res) {
|
|
134
|
+
try {
|
|
135
|
+
res.json({ success: true, data: await getDeps().canva.getDesign(String(req.params.id ?? '')) });
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
sendCanvaError(req, res, err);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** POST /api/canva/designs — `{ title?, preset?, width?, height?, assetId? }` */
|
|
142
|
+
export async function createDesign(req, res) {
|
|
143
|
+
try {
|
|
144
|
+
const body = (req.body ?? {});
|
|
145
|
+
const design = await getDeps().canva.createDesign({ title: body.title, preset: body.preset, width: body.width, height: body.height, assetId: body.assetId });
|
|
146
|
+
logger.info('Canva design created', { id: design.id, title: design.title });
|
|
147
|
+
res.json({ success: true, data: design });
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
sendCanvaError(req, res, err);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** POST /api/canva/designs/:id/export — `{ format, quality?, videoQuality?, pages? }` */
|
|
154
|
+
export async function exportDesign(req, res) {
|
|
155
|
+
try {
|
|
156
|
+
const body = (req.body ?? {});
|
|
157
|
+
const out = await getDeps().canva.exportDesign({
|
|
158
|
+
designId: String(req.params.id ?? ''),
|
|
159
|
+
format: String(body.format ?? ''),
|
|
160
|
+
quality: body.quality,
|
|
161
|
+
videoQuality: body.videoQuality,
|
|
162
|
+
pages: Array.isArray(body.pages) ? body.pages : undefined,
|
|
163
|
+
});
|
|
164
|
+
res.json({ success: out.status === 'success', data: out });
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
sendCanvaError(req, res, err);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** POST /api/canva/assets — `{ name, content (base64) }` */
|
|
171
|
+
export async function uploadAsset(req, res) {
|
|
172
|
+
try {
|
|
173
|
+
const body = (req.body ?? {});
|
|
174
|
+
const bytes = typeof body.content === 'string' ? Buffer.from(body.content, 'base64') : Buffer.alloc(0);
|
|
175
|
+
const asset = await getDeps().canva.uploadAsset(String(body.name ?? ''), bytes);
|
|
176
|
+
logger.info('Canva asset uploaded', { id: asset.id, name: asset.name, bytes: bytes.length });
|
|
177
|
+
res.json({ success: true, data: asset });
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
sendCanvaError(req, res, err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=canva.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/canva/canva.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canva routes — mounted at `/api/canva`.
|
|
3
|
+
*
|
|
4
|
+
* - GET /status — grant status
|
|
5
|
+
* - GET /connect-url — Cloud consent-start URL
|
|
6
|
+
* - DELETE /disconnect — revoke + forget
|
|
7
|
+
* - GET /designs — ?q=&ownership=&sort=&limit=&continuation=
|
|
8
|
+
* - GET /designs/:id — one design
|
|
9
|
+
* - POST /designs — { title?, preset?, width?, height?, assetId? }
|
|
10
|
+
* - POST /designs/:id/export — { format, quality?, videoQuality?, pages? }
|
|
11
|
+
* - POST /assets — { name, content: base64 }
|
|
12
|
+
*
|
|
13
|
+
* @module controllers/canva/canva.routes
|
|
14
|
+
*/
|
|
15
|
+
import { Router } from 'express';
|
|
16
|
+
/**
|
|
17
|
+
* Creates the Canva router.
|
|
18
|
+
*
|
|
19
|
+
* @returns Express router
|
|
20
|
+
*/
|
|
21
|
+
export declare function createCanvaRouter(): Router;
|
|
22
|
+
//# sourceMappingURL=canva.routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva.routes.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/canva/canva.routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAW1C"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canva routes — mounted at `/api/canva`.
|
|
3
|
+
*
|
|
4
|
+
* - GET /status — grant status
|
|
5
|
+
* - GET /connect-url — Cloud consent-start URL
|
|
6
|
+
* - DELETE /disconnect — revoke + forget
|
|
7
|
+
* - GET /designs — ?q=&ownership=&sort=&limit=&continuation=
|
|
8
|
+
* - GET /designs/:id — one design
|
|
9
|
+
* - POST /designs — { title?, preset?, width?, height?, assetId? }
|
|
10
|
+
* - POST /designs/:id/export — { format, quality?, videoQuality?, pages? }
|
|
11
|
+
* - POST /assets — { name, content: base64 }
|
|
12
|
+
*
|
|
13
|
+
* @module controllers/canva/canva.routes
|
|
14
|
+
*/
|
|
15
|
+
import { Router } from 'express';
|
|
16
|
+
import { getStatus, getConnectUrl, disconnect, listDesigns, getDesign, createDesign, exportDesign, uploadAsset } from './canva.controller.js';
|
|
17
|
+
/**
|
|
18
|
+
* Creates the Canva router.
|
|
19
|
+
*
|
|
20
|
+
* @returns Express router
|
|
21
|
+
*/
|
|
22
|
+
export function createCanvaRouter() {
|
|
23
|
+
const router = Router();
|
|
24
|
+
router.get('/status', getStatus);
|
|
25
|
+
router.get('/connect-url', getConnectUrl);
|
|
26
|
+
router.delete('/disconnect', disconnect);
|
|
27
|
+
router.get('/designs', listDesigns);
|
|
28
|
+
router.get('/designs/:id', getDesign);
|
|
29
|
+
router.post('/designs', createDesign);
|
|
30
|
+
router.post('/designs/:id/export', exportDesign);
|
|
31
|
+
router.post('/assets', uploadAsset);
|
|
32
|
+
return router;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=canva.routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/canva/canva.routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE9I;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAC1C,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACtC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -15,11 +15,19 @@ import type { Request, Response } from 'express';
|
|
|
15
15
|
import { GoogleWorkspaceTokenService } from '../../services/google/google-workspace-token.service.js';
|
|
16
16
|
import { GmailService } from '../../services/google/gmail.service.js';
|
|
17
17
|
import { CalendarService } from '../../services/google/calendar.service.js';
|
|
18
|
+
import { DriveService } from '../../services/google/drive.service.js';
|
|
19
|
+
import { DocsService } from '../../services/google/docs.service.js';
|
|
20
|
+
import { SheetsService } from '../../services/google/sheets.service.js';
|
|
21
|
+
import { SlidesService } from '../../services/google/slides.service.js';
|
|
18
22
|
/** The services the handlers use; swappable for tests. */
|
|
19
23
|
export interface GoogleControllerDeps {
|
|
20
24
|
tokens: GoogleWorkspaceTokenService;
|
|
21
25
|
gmail: GmailService;
|
|
22
26
|
calendar: CalendarService;
|
|
27
|
+
drive: DriveService;
|
|
28
|
+
docs: DocsService;
|
|
29
|
+
sheets: SheetsService;
|
|
30
|
+
slides: SlidesService;
|
|
23
31
|
}
|
|
24
32
|
/**
|
|
25
33
|
* Replace (or, with null, reset) the services the handlers use. Tests only.
|
|
@@ -97,4 +105,96 @@ export declare function calendarList(req: Request, res: Response): Promise<void>
|
|
|
97
105
|
* @param res - Response
|
|
98
106
|
*/
|
|
99
107
|
export declare function calendarCreate(req: Request, res: Response): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* GET /api/google/drive/files?q=&mimeType=&folderId=&max= — search.
|
|
110
|
+
*
|
|
111
|
+
* @param req - Incoming request
|
|
112
|
+
* @param res - Response
|
|
113
|
+
*/
|
|
114
|
+
export declare function driveSearch(req: Request, res: Response): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* GET /api/google/drive/files/:id — metadata.
|
|
117
|
+
*
|
|
118
|
+
* @param req - Incoming request
|
|
119
|
+
* @param res - Response
|
|
120
|
+
*/
|
|
121
|
+
export declare function driveGet(req: Request, res: Response): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* GET /api/google/drive/files/:id/content — exported text / downloaded body.
|
|
124
|
+
*
|
|
125
|
+
* @param req - Incoming request
|
|
126
|
+
* @param res - Response
|
|
127
|
+
*/
|
|
128
|
+
export declare function driveContent(req: Request, res: Response): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* POST /api/google/drive/files — body `{ name, content, encoding?, mimeType?, folderId?, convertTo? }`.
|
|
131
|
+
*
|
|
132
|
+
* @param req - Incoming request
|
|
133
|
+
* @param res - Response
|
|
134
|
+
*/
|
|
135
|
+
export declare function driveUpload(req: Request, res: Response): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* GET /api/google/docs/:id — document as text.
|
|
138
|
+
*
|
|
139
|
+
* @param req - Incoming request
|
|
140
|
+
* @param res - Response
|
|
141
|
+
*/
|
|
142
|
+
export declare function docsRead(req: Request, res: Response): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* POST /api/google/docs — body `{ title, text? }`.
|
|
145
|
+
*
|
|
146
|
+
* @param req - Incoming request
|
|
147
|
+
* @param res - Response
|
|
148
|
+
*/
|
|
149
|
+
export declare function docsCreate(req: Request, res: Response): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* POST /api/google/docs/:id/append — body `{ text }`.
|
|
152
|
+
*
|
|
153
|
+
* @param req - Incoming request
|
|
154
|
+
* @param res - Response
|
|
155
|
+
*/
|
|
156
|
+
export declare function docsAppend(req: Request, res: Response): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* GET /api/google/sheets/:id — title + tabs.
|
|
159
|
+
*
|
|
160
|
+
* @param req - Incoming request
|
|
161
|
+
* @param res - Response
|
|
162
|
+
*/
|
|
163
|
+
export declare function sheetsInfo(req: Request, res: Response): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* GET /api/google/sheets/:id/values?range= — cell values.
|
|
166
|
+
*
|
|
167
|
+
* @param req - Incoming request
|
|
168
|
+
* @param res - Response
|
|
169
|
+
*/
|
|
170
|
+
export declare function sheetsRead(req: Request, res: Response): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* POST /api/google/sheets — body `{ title, sheetTitle?, rows? }`.
|
|
173
|
+
*
|
|
174
|
+
* @param req - Incoming request
|
|
175
|
+
* @param res - Response
|
|
176
|
+
*/
|
|
177
|
+
export declare function sheetsCreate(req: Request, res: Response): Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* POST /api/google/sheets/:id/values — body `{ range?, rows, mode?: 'append' | 'update' }`
|
|
180
|
+
* (default append).
|
|
181
|
+
*
|
|
182
|
+
* @param req - Incoming request
|
|
183
|
+
* @param res - Response
|
|
184
|
+
*/
|
|
185
|
+
export declare function sheetsWrite(req: Request, res: Response): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* GET /api/google/slides/:id — deck as text per slide.
|
|
188
|
+
*
|
|
189
|
+
* @param req - Incoming request
|
|
190
|
+
* @param res - Response
|
|
191
|
+
*/
|
|
192
|
+
export declare function slidesRead(req: Request, res: Response): Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* POST /api/google/slides — body `{ title, slides: [{ title, bullets? }] }`.
|
|
195
|
+
*
|
|
196
|
+
* @param req - Incoming request
|
|
197
|
+
* @param res - Response
|
|
198
|
+
*/
|
|
199
|
+
export declare function slidesCreate(req: Request, res: Response): Promise<void>;
|
|
100
200
|
//# sourceMappingURL=google.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGjD,OAAO,EACL,2BAA2B,EAE5B,MAAM,yDAAyD,CAAC;AACjE,OAAO,EAAE,YAAY,EAAoC,MAAM,wCAAwC,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,10 @@ import { LoggerService } from '../../services/core/logger.service.js';
|
|
|
16
16
|
import { GoogleWorkspaceTokenService, GoogleWorkspaceError, } from '../../services/google/google-workspace-token.service.js';
|
|
17
17
|
import { GmailService, buildRfc822 } from '../../services/google/gmail.service.js';
|
|
18
18
|
import { CalendarService } from '../../services/google/calendar.service.js';
|
|
19
|
+
import { DriveService } from '../../services/google/drive.service.js';
|
|
20
|
+
import { DocsService } from '../../services/google/docs.service.js';
|
|
21
|
+
import { SheetsService } from '../../services/google/sheets.service.js';
|
|
22
|
+
import { SlidesService } from '../../services/google/slides.service.js';
|
|
19
23
|
const logger = LoggerService.getInstance().createComponentLogger('GoogleController');
|
|
20
24
|
let deps = null;
|
|
21
25
|
/**
|
|
@@ -27,7 +31,15 @@ let deps = null;
|
|
|
27
31
|
function getDeps() {
|
|
28
32
|
if (!deps) {
|
|
29
33
|
const tokens = GoogleWorkspaceTokenService.getInstance();
|
|
30
|
-
deps = {
|
|
34
|
+
deps = {
|
|
35
|
+
tokens,
|
|
36
|
+
gmail: new GmailService({ tokens }),
|
|
37
|
+
calendar: new CalendarService({ tokens }),
|
|
38
|
+
drive: new DriveService({ tokens }),
|
|
39
|
+
docs: new DocsService({ tokens }),
|
|
40
|
+
sheets: new SheetsService({ tokens }),
|
|
41
|
+
slides: new SlidesService({ tokens }),
|
|
42
|
+
};
|
|
31
43
|
}
|
|
32
44
|
return deps;
|
|
33
45
|
}
|
|
@@ -290,4 +302,228 @@ export async function calendarCreate(req, res) {
|
|
|
290
302
|
sendGoogleError(req, res, err);
|
|
291
303
|
}
|
|
292
304
|
}
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// Drive
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
/**
|
|
309
|
+
* GET /api/google/drive/files?q=&mimeType=&folderId=&max= — search.
|
|
310
|
+
*
|
|
311
|
+
* @param req - Incoming request
|
|
312
|
+
* @param res - Response
|
|
313
|
+
*/
|
|
314
|
+
export async function driveSearch(req, res) {
|
|
315
|
+
try {
|
|
316
|
+
const files = await getDeps().drive.search({
|
|
317
|
+
query: q(req, 'q') || undefined,
|
|
318
|
+
mimeType: q(req, 'mimeType') || undefined,
|
|
319
|
+
folderId: q(req, 'folderId') || undefined,
|
|
320
|
+
max: qInt(req, 'max'),
|
|
321
|
+
});
|
|
322
|
+
res.json({ success: true, data: { count: files.length, files } });
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
sendGoogleError(req, res, err);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* GET /api/google/drive/files/:id — metadata.
|
|
330
|
+
*
|
|
331
|
+
* @param req - Incoming request
|
|
332
|
+
* @param res - Response
|
|
333
|
+
*/
|
|
334
|
+
export async function driveGet(req, res) {
|
|
335
|
+
try {
|
|
336
|
+
res.json({ success: true, data: await getDeps().drive.get(String(req.params.id ?? '')) });
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
sendGoogleError(req, res, err);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* GET /api/google/drive/files/:id/content — exported text / downloaded body.
|
|
344
|
+
*
|
|
345
|
+
* @param req - Incoming request
|
|
346
|
+
* @param res - Response
|
|
347
|
+
*/
|
|
348
|
+
export async function driveContent(req, res) {
|
|
349
|
+
try {
|
|
350
|
+
res.json({ success: true, data: await getDeps().drive.readContent(String(req.params.id ?? '')) });
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
sendGoogleError(req, res, err);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* POST /api/google/drive/files — body `{ name, content, encoding?, mimeType?, folderId?, convertTo? }`.
|
|
358
|
+
*
|
|
359
|
+
* @param req - Incoming request
|
|
360
|
+
* @param res - Response
|
|
361
|
+
*/
|
|
362
|
+
export async function driveUpload(req, res) {
|
|
363
|
+
try {
|
|
364
|
+
const body = (req.body ?? {});
|
|
365
|
+
const file = await getDeps().drive.upload({
|
|
366
|
+
name: String(body.name ?? ''),
|
|
367
|
+
content: typeof body.content === 'string' ? body.content : '',
|
|
368
|
+
encoding: body.encoding === 'base64' ? 'base64' : 'utf8',
|
|
369
|
+
mimeType: body.mimeType,
|
|
370
|
+
folderId: body.folderId,
|
|
371
|
+
convertTo: body.convertTo,
|
|
372
|
+
});
|
|
373
|
+
logger.info('Drive file uploaded', { id: file.id, name: file.name });
|
|
374
|
+
res.json({ success: true, data: file });
|
|
375
|
+
}
|
|
376
|
+
catch (err) {
|
|
377
|
+
sendGoogleError(req, res, err);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// ---------------------------------------------------------------------------
|
|
381
|
+
// Docs
|
|
382
|
+
// ---------------------------------------------------------------------------
|
|
383
|
+
/**
|
|
384
|
+
* GET /api/google/docs/:id — document as text.
|
|
385
|
+
*
|
|
386
|
+
* @param req - Incoming request
|
|
387
|
+
* @param res - Response
|
|
388
|
+
*/
|
|
389
|
+
export async function docsRead(req, res) {
|
|
390
|
+
try {
|
|
391
|
+
res.json({ success: true, data: await getDeps().docs.read(String(req.params.id ?? '')) });
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
sendGoogleError(req, res, err);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* POST /api/google/docs — body `{ title, text? }`.
|
|
399
|
+
*
|
|
400
|
+
* @param req - Incoming request
|
|
401
|
+
* @param res - Response
|
|
402
|
+
*/
|
|
403
|
+
export async function docsCreate(req, res) {
|
|
404
|
+
try {
|
|
405
|
+
const body = (req.body ?? {});
|
|
406
|
+
const doc = await getDeps().docs.create({ title: String(body.title ?? ''), text: typeof body.text === 'string' ? body.text : undefined });
|
|
407
|
+
logger.info('Google Doc created', { id: doc.id, title: doc.title });
|
|
408
|
+
res.json({ success: true, data: doc });
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
sendGoogleError(req, res, err);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* POST /api/google/docs/:id/append — body `{ text }`.
|
|
416
|
+
*
|
|
417
|
+
* @param req - Incoming request
|
|
418
|
+
* @param res - Response
|
|
419
|
+
*/
|
|
420
|
+
export async function docsAppend(req, res) {
|
|
421
|
+
try {
|
|
422
|
+
const body = (req.body ?? {});
|
|
423
|
+
res.json({ success: true, data: await getDeps().docs.append(String(req.params.id ?? ''), String(body.text ?? '')) });
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
sendGoogleError(req, res, err);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
// Sheets
|
|
431
|
+
// ---------------------------------------------------------------------------
|
|
432
|
+
/**
|
|
433
|
+
* GET /api/google/sheets/:id — title + tabs.
|
|
434
|
+
*
|
|
435
|
+
* @param req - Incoming request
|
|
436
|
+
* @param res - Response
|
|
437
|
+
*/
|
|
438
|
+
export async function sheetsInfo(req, res) {
|
|
439
|
+
try {
|
|
440
|
+
res.json({ success: true, data: await getDeps().sheets.info(String(req.params.id ?? '')) });
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
sendGoogleError(req, res, err);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* GET /api/google/sheets/:id/values?range= — cell values.
|
|
448
|
+
*
|
|
449
|
+
* @param req - Incoming request
|
|
450
|
+
* @param res - Response
|
|
451
|
+
*/
|
|
452
|
+
export async function sheetsRead(req, res) {
|
|
453
|
+
try {
|
|
454
|
+
res.json({ success: true, data: await getDeps().sheets.read(String(req.params.id ?? ''), q(req, 'range') || undefined) });
|
|
455
|
+
}
|
|
456
|
+
catch (err) {
|
|
457
|
+
sendGoogleError(req, res, err);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* POST /api/google/sheets — body `{ title, sheetTitle?, rows? }`.
|
|
462
|
+
*
|
|
463
|
+
* @param req - Incoming request
|
|
464
|
+
* @param res - Response
|
|
465
|
+
*/
|
|
466
|
+
export async function sheetsCreate(req, res) {
|
|
467
|
+
try {
|
|
468
|
+
const body = (req.body ?? {});
|
|
469
|
+
const info = await getDeps().sheets.create({ title: String(body.title ?? ''), sheetTitle: body.sheetTitle, rows: body.rows });
|
|
470
|
+
logger.info('Google Sheet created', { id: info.id, title: info.title });
|
|
471
|
+
res.json({ success: true, data: info });
|
|
472
|
+
}
|
|
473
|
+
catch (err) {
|
|
474
|
+
sendGoogleError(req, res, err);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* POST /api/google/sheets/:id/values — body `{ range?, rows, mode?: 'append' | 'update' }`
|
|
479
|
+
* (default append).
|
|
480
|
+
*
|
|
481
|
+
* @param req - Incoming request
|
|
482
|
+
* @param res - Response
|
|
483
|
+
*/
|
|
484
|
+
export async function sheetsWrite(req, res) {
|
|
485
|
+
try {
|
|
486
|
+
const body = (req.body ?? {});
|
|
487
|
+
const input = { spreadsheetId: String(req.params.id ?? ''), range: body.range, rows: body.rows };
|
|
488
|
+
const result = body.mode === 'update' ? await getDeps().sheets.update(input) : await getDeps().sheets.append(input);
|
|
489
|
+
res.json({ success: true, data: { mode: body.mode === 'update' ? 'update' : 'append', ...result } });
|
|
490
|
+
}
|
|
491
|
+
catch (err) {
|
|
492
|
+
sendGoogleError(req, res, err);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// ---------------------------------------------------------------------------
|
|
496
|
+
// Slides
|
|
497
|
+
// ---------------------------------------------------------------------------
|
|
498
|
+
/**
|
|
499
|
+
* GET /api/google/slides/:id — deck as text per slide.
|
|
500
|
+
*
|
|
501
|
+
* @param req - Incoming request
|
|
502
|
+
* @param res - Response
|
|
503
|
+
*/
|
|
504
|
+
export async function slidesRead(req, res) {
|
|
505
|
+
try {
|
|
506
|
+
res.json({ success: true, data: await getDeps().slides.read(String(req.params.id ?? '')) });
|
|
507
|
+
}
|
|
508
|
+
catch (err) {
|
|
509
|
+
sendGoogleError(req, res, err);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* POST /api/google/slides — body `{ title, slides: [{ title, bullets? }] }`.
|
|
514
|
+
*
|
|
515
|
+
* @param req - Incoming request
|
|
516
|
+
* @param res - Response
|
|
517
|
+
*/
|
|
518
|
+
export async function slidesCreate(req, res) {
|
|
519
|
+
try {
|
|
520
|
+
const body = (req.body ?? {});
|
|
521
|
+
const deck = await getDeps().slides.create({ title: String(body.title ?? ''), slides: Array.isArray(body.slides) ? body.slides : [] });
|
|
522
|
+
logger.info('Google Slides deck created', { id: deck.id, title: deck.title, slides: deck.slideCount });
|
|
523
|
+
res.json({ success: true, data: deck });
|
|
524
|
+
}
|
|
525
|
+
catch (err) {
|
|
526
|
+
sendGoogleError(req, res, err);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
293
529
|
//# sourceMappingURL=google.controller.js.map
|