crewly 1.20.29 → 1.20.31
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/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +22 -4
- package/dist/backend/backend/src/services/agent/agent-registration.service.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/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/utils/tool-call-markup.utils.d.ts +45 -0
- package/dist/backend/backend/src/utils/tool-call-markup.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/tool-call-markup.utils.js +83 -0
- package/dist/backend/backend/src/utils/tool-call-markup.utils.js.map +1 -0
- 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/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +22 -4
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/utils/tool-call-markup.utils.d.ts +45 -0
- package/dist/cli/backend/src/utils/tool-call-markup.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/tool-call-markup.utils.js +83 -0
- package/dist/cli/backend/src/utils/tool-call-markup.utils.js.map +1 -0
- 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,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CanvaTokenService — the Canva access token for this instance, minted by
|
|
3
|
+
* Crewly Cloud from the owner's grant (`/api/cloud/canva/token`).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors GoogleWorkspaceTokenService: Cloud keeps the client secret and the
|
|
6
|
+
* (single-use, rotating) refresh token; this side caches the access token
|
|
7
|
+
* until a minute before expiry and shares one in-flight refresh.
|
|
8
|
+
*
|
|
9
|
+
* @module services/canva/canva-token.service
|
|
10
|
+
*/
|
|
11
|
+
/** The slice of the Cloud client the service needs (injectable for tests). */
|
|
12
|
+
export interface CanvaCloudClient {
|
|
13
|
+
isConnected(): boolean;
|
|
14
|
+
getToken(): string | null;
|
|
15
|
+
getCloudUrl(): string | null;
|
|
16
|
+
}
|
|
17
|
+
/** Constructor dependencies. */
|
|
18
|
+
export interface CanvaTokenServiceDeps {
|
|
19
|
+
cloud?: CanvaCloudClient;
|
|
20
|
+
fetchImpl?: typeof fetch;
|
|
21
|
+
now?: () => number;
|
|
22
|
+
}
|
|
23
|
+
/** `GET /api/canva/status` payload. */
|
|
24
|
+
export interface CanvaStatus {
|
|
25
|
+
connected: boolean;
|
|
26
|
+
cloudConnected: boolean;
|
|
27
|
+
canvaUserId?: string;
|
|
28
|
+
canvaTeamId?: string;
|
|
29
|
+
displayName?: string;
|
|
30
|
+
scopes?: string[];
|
|
31
|
+
grantedAt?: string;
|
|
32
|
+
}
|
|
33
|
+
/** A Canva failure with the HTTP status the controller answers with. */
|
|
34
|
+
export declare class CanvaError extends Error {
|
|
35
|
+
readonly status: number;
|
|
36
|
+
readonly code: string;
|
|
37
|
+
constructor(status: number, code: string, message: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Map a Cloud grant-endpoint failure onto this instance's error codes.
|
|
41
|
+
*
|
|
42
|
+
* @param httpStatus - Cloud HTTP status
|
|
43
|
+
* @param code - Cloud `error` / `code`
|
|
44
|
+
* @param message - Cloud message
|
|
45
|
+
* @returns The mapped error
|
|
46
|
+
*/
|
|
47
|
+
export declare function mapCloudFailure(httpStatus: number, code: string | undefined, message: string | undefined): CanvaError;
|
|
48
|
+
/**
|
|
49
|
+
* Access-token provider for the Canva API.
|
|
50
|
+
*/
|
|
51
|
+
export declare class CanvaTokenService {
|
|
52
|
+
private static instance;
|
|
53
|
+
private readonly logger;
|
|
54
|
+
private readonly cloud;
|
|
55
|
+
private readonly fetchImpl;
|
|
56
|
+
private readonly nowFn;
|
|
57
|
+
private cached;
|
|
58
|
+
private inflight;
|
|
59
|
+
constructor(deps?: CanvaTokenServiceDeps);
|
|
60
|
+
static getInstance(): CanvaTokenService;
|
|
61
|
+
static resetInstance(): void;
|
|
62
|
+
isCloudAvailable(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* A usable access token (cached until 60 s before expiry).
|
|
65
|
+
*
|
|
66
|
+
* @returns The token
|
|
67
|
+
* @throws CanvaError not_logged_in / not_connected / not_configured / canva_error / network
|
|
68
|
+
*/
|
|
69
|
+
getAccessToken(): Promise<string>;
|
|
70
|
+
/** Forget the cached token (after a Canva 401 or a disconnect). */
|
|
71
|
+
clearCache(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Whether Cloud holds a Canva grant; "not there" cases come back as
|
|
74
|
+
* `connected: false`, outages throw.
|
|
75
|
+
*
|
|
76
|
+
* @returns Status
|
|
77
|
+
*/
|
|
78
|
+
status(): Promise<CanvaStatus>;
|
|
79
|
+
/**
|
|
80
|
+
* Ask Cloud to revoke and forget the grant.
|
|
81
|
+
*
|
|
82
|
+
* @returns Whether Cloud had one
|
|
83
|
+
*/
|
|
84
|
+
disconnect(): Promise<{
|
|
85
|
+
removed: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* The Cloud consent-start URL for the browser.
|
|
89
|
+
*
|
|
90
|
+
* @param returnUrl - Absolute dashboard URL Cloud redirects back to
|
|
91
|
+
* @returns URL to open
|
|
92
|
+
* @throws CanvaError(401, not_logged_in) when not signed in to Cloud
|
|
93
|
+
*/
|
|
94
|
+
buildConnectUrl(returnUrl: string): string;
|
|
95
|
+
private refresh;
|
|
96
|
+
private cloudRequest;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=canva-token.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva-token.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/canva/canva-token.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,gCAAgC;AAChC,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoBD,wEAAwE;AACxE,qBAAa,UAAW,SAAQ,KAAK;aAEjB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAerH;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,QAAQ,CAAgC;gBAEpC,IAAI,GAAE,qBAA0B;IAO5C,MAAM,CAAC,WAAW,IAAI,iBAAiB;IAKvC,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B,gBAAgB,IAAI,OAAO;IAI3B;;;;;OAKG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IASvC,mEAAmE;IACnE,UAAU,IAAI,IAAI;IAIlB;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC;IAuBpC;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAMjD;;;;;;OAMG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;YAY5B,OAAO;YAcP,YAAY;CAuB3B"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CanvaTokenService — the Canva access token for this instance, minted by
|
|
3
|
+
* Crewly Cloud from the owner's grant (`/api/cloud/canva/token`).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors GoogleWorkspaceTokenService: Cloud keeps the client secret and the
|
|
6
|
+
* (single-use, rotating) refresh token; this side caches the access token
|
|
7
|
+
* until a minute before expiry and shares one in-flight refresh.
|
|
8
|
+
*
|
|
9
|
+
* @module services/canva/canva-token.service
|
|
10
|
+
*/
|
|
11
|
+
import { CloudClientService } from '../cloud/cloud-client.service.js';
|
|
12
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
13
|
+
import { CANVA_CONSTANTS } from '../../constants.js';
|
|
14
|
+
/** A Canva failure with the HTTP status the controller answers with. */
|
|
15
|
+
export class CanvaError extends Error {
|
|
16
|
+
status;
|
|
17
|
+
code;
|
|
18
|
+
constructor(status, code, message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.code = code;
|
|
22
|
+
this.name = 'CanvaError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Map a Cloud grant-endpoint failure onto this instance's error codes.
|
|
27
|
+
*
|
|
28
|
+
* @param httpStatus - Cloud HTTP status
|
|
29
|
+
* @param code - Cloud `error` / `code`
|
|
30
|
+
* @param message - Cloud message
|
|
31
|
+
* @returns The mapped error
|
|
32
|
+
*/
|
|
33
|
+
export function mapCloudFailure(httpStatus, code, message) {
|
|
34
|
+
const CODES = CANVA_CONSTANTS.ERROR_CODES;
|
|
35
|
+
if (httpStatus === 401 || httpStatus === 403) {
|
|
36
|
+
return new CanvaError(401, CODES.NOT_LOGGED_IN, 'Crewly Cloud session expired. Sign in to Crewly Cloud again.');
|
|
37
|
+
}
|
|
38
|
+
if (httpStatus === 404 || httpStatus === 409 || code === CODES.NOT_CONNECTED || code === 'grant_revoked') {
|
|
39
|
+
return new CanvaError(409, CODES.NOT_CONNECTED, 'Canva is not connected for this Crewly Cloud account.');
|
|
40
|
+
}
|
|
41
|
+
if (httpStatus === 503 || code === CODES.NOT_CONFIGURED) {
|
|
42
|
+
return new CanvaError(503, CODES.NOT_CONFIGURED, 'Crewly Cloud is not configured for Canva.');
|
|
43
|
+
}
|
|
44
|
+
if (httpStatus === 502 || code === CODES.CANVA_ERROR) {
|
|
45
|
+
return new CanvaError(502, CODES.CANVA_ERROR, message || 'Canva rejected the token request.');
|
|
46
|
+
}
|
|
47
|
+
return new CanvaError(502, code ?? `http_${httpStatus}`, message || `Cloud request failed (${httpStatus})`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Access-token provider for the Canva API.
|
|
51
|
+
*/
|
|
52
|
+
export class CanvaTokenService {
|
|
53
|
+
static instance = null;
|
|
54
|
+
logger;
|
|
55
|
+
cloud;
|
|
56
|
+
fetchImpl;
|
|
57
|
+
nowFn;
|
|
58
|
+
cached = null;
|
|
59
|
+
inflight = null;
|
|
60
|
+
constructor(deps = {}) {
|
|
61
|
+
this.logger = LoggerService.getInstance().createComponentLogger('CanvaToken');
|
|
62
|
+
this.cloud = deps.cloud ?? CloudClientService.getInstance();
|
|
63
|
+
this.fetchImpl = deps.fetchImpl ?? fetch;
|
|
64
|
+
this.nowFn = deps.now ?? (() => Date.now());
|
|
65
|
+
}
|
|
66
|
+
static getInstance() {
|
|
67
|
+
if (!CanvaTokenService.instance)
|
|
68
|
+
CanvaTokenService.instance = new CanvaTokenService();
|
|
69
|
+
return CanvaTokenService.instance;
|
|
70
|
+
}
|
|
71
|
+
static resetInstance() {
|
|
72
|
+
CanvaTokenService.instance = null;
|
|
73
|
+
}
|
|
74
|
+
isCloudAvailable() {
|
|
75
|
+
return this.cloud.isConnected() && !!this.cloud.getToken() && !!this.cloud.getCloudUrl();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A usable access token (cached until 60 s before expiry).
|
|
79
|
+
*
|
|
80
|
+
* @returns The token
|
|
81
|
+
* @throws CanvaError not_logged_in / not_connected / not_configured / canva_error / network
|
|
82
|
+
*/
|
|
83
|
+
async getAccessToken() {
|
|
84
|
+
if (this.cached && this.cached.expiresAtMs - CANVA_CONSTANTS.TOKEN_REFRESH_MARGIN_MS > this.nowFn())
|
|
85
|
+
return this.cached.accessToken;
|
|
86
|
+
if (this.inflight)
|
|
87
|
+
return this.inflight;
|
|
88
|
+
this.inflight = this.refresh().finally(() => {
|
|
89
|
+
this.inflight = null;
|
|
90
|
+
});
|
|
91
|
+
return this.inflight;
|
|
92
|
+
}
|
|
93
|
+
/** Forget the cached token (after a Canva 401 or a disconnect). */
|
|
94
|
+
clearCache() {
|
|
95
|
+
this.cached = null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether Cloud holds a Canva grant; "not there" cases come back as
|
|
99
|
+
* `connected: false`, outages throw.
|
|
100
|
+
*
|
|
101
|
+
* @returns Status
|
|
102
|
+
*/
|
|
103
|
+
async status() {
|
|
104
|
+
if (!this.isCloudAvailable())
|
|
105
|
+
return { connected: false, cloudConnected: false };
|
|
106
|
+
try {
|
|
107
|
+
const data = await this.cloudRequest('GET', CANVA_CONSTANTS.CLOUD_ENDPOINTS.STATUS);
|
|
108
|
+
if (!data.connected)
|
|
109
|
+
this.clearCache();
|
|
110
|
+
return {
|
|
111
|
+
connected: !!data.connected,
|
|
112
|
+
cloudConnected: true,
|
|
113
|
+
...(data.canvaUserId ? { canvaUserId: data.canvaUserId } : {}),
|
|
114
|
+
...(data.canvaTeamId ? { canvaTeamId: data.canvaTeamId } : {}),
|
|
115
|
+
...(data.displayName ? { displayName: data.displayName } : {}),
|
|
116
|
+
...(data.scopes ? { scopes: data.scopes } : {}),
|
|
117
|
+
...(data.grantedAt ? { grantedAt: data.grantedAt } : {}),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
if (err instanceof CanvaError && err.code === CANVA_CONSTANTS.ERROR_CODES.NOT_CONNECTED) {
|
|
122
|
+
this.clearCache();
|
|
123
|
+
return { connected: false, cloudConnected: true };
|
|
124
|
+
}
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Ask Cloud to revoke and forget the grant.
|
|
130
|
+
*
|
|
131
|
+
* @returns Whether Cloud had one
|
|
132
|
+
*/
|
|
133
|
+
async disconnect() {
|
|
134
|
+
this.clearCache();
|
|
135
|
+
const data = await this.cloudRequest('DELETE', CANVA_CONSTANTS.CLOUD_ENDPOINTS.DISCONNECT);
|
|
136
|
+
return { removed: !!data.removed };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The Cloud consent-start URL for the browser.
|
|
140
|
+
*
|
|
141
|
+
* @param returnUrl - Absolute dashboard URL Cloud redirects back to
|
|
142
|
+
* @returns URL to open
|
|
143
|
+
* @throws CanvaError(401, not_logged_in) when not signed in to Cloud
|
|
144
|
+
*/
|
|
145
|
+
buildConnectUrl(returnUrl) {
|
|
146
|
+
const token = this.cloud.getToken();
|
|
147
|
+
const base = this.cloud.getCloudUrl();
|
|
148
|
+
if (!this.isCloudAvailable() || !token || !base) {
|
|
149
|
+
throw new CanvaError(401, CANVA_CONSTANTS.ERROR_CODES.NOT_LOGGED_IN, 'Sign in to Crewly Cloud first.');
|
|
150
|
+
}
|
|
151
|
+
const url = new URL(`${base.replace(/\/$/, '')}${CANVA_CONSTANTS.CLOUD_PATH}${CANVA_CONSTANTS.CLOUD_ENDPOINTS.START}`);
|
|
152
|
+
url.searchParams.set('token', token);
|
|
153
|
+
url.searchParams.set('returnUrl', returnUrl);
|
|
154
|
+
return url.toString();
|
|
155
|
+
}
|
|
156
|
+
async refresh() {
|
|
157
|
+
try {
|
|
158
|
+
const data = await this.cloudRequest('GET', CANVA_CONSTANTS.CLOUD_ENDPOINTS.TOKEN);
|
|
159
|
+
if (!data.accessToken)
|
|
160
|
+
throw new CanvaError(502, CANVA_CONSTANTS.ERROR_CODES.CANVA_ERROR, 'Cloud returned no access token.');
|
|
161
|
+
const expiresAtMs = Date.parse(data.expiresAt);
|
|
162
|
+
this.cached = { accessToken: data.accessToken, expiresAtMs: Number.isFinite(expiresAtMs) ? expiresAtMs : this.nowFn() };
|
|
163
|
+
this.logger.debug('Canva access token refreshed', { expiresAt: data.expiresAt });
|
|
164
|
+
return data.accessToken;
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
this.cached = null;
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async cloudRequest(method, suffix) {
|
|
172
|
+
const token = this.cloud.getToken();
|
|
173
|
+
const base = this.cloud.getCloudUrl();
|
|
174
|
+
if (!this.isCloudAvailable() || !token || !base) {
|
|
175
|
+
throw new CanvaError(401, CANVA_CONSTANTS.ERROR_CODES.NOT_LOGGED_IN, 'Not signed in to Crewly Cloud.');
|
|
176
|
+
}
|
|
177
|
+
const url = `${base.replace(/\/$/, '')}${CANVA_CONSTANTS.CLOUD_PATH}${suffix}`;
|
|
178
|
+
let res;
|
|
179
|
+
try {
|
|
180
|
+
res = await this.fetchImpl(url, { method, headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(CANVA_CONSTANTS.REQUEST_TIMEOUT_MS) });
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
throw new CanvaError(502, CANVA_CONSTANTS.ERROR_CODES.NETWORK, `Crewly Cloud unreachable: ${err instanceof Error ? err.message : String(err)}`);
|
|
184
|
+
}
|
|
185
|
+
const text = await res.text();
|
|
186
|
+
let parsed = {};
|
|
187
|
+
try {
|
|
188
|
+
parsed = JSON.parse(text);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
parsed = {};
|
|
192
|
+
}
|
|
193
|
+
if (!res.ok || parsed.success !== true)
|
|
194
|
+
throw mapCloudFailure(res.status, parsed.code ?? parsed.error, parsed.error);
|
|
195
|
+
return (parsed.data ?? {});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=canva-token.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva-token.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/canva/canva-token.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CanvaService — Canva Connect REST on the owner's grant.
|
|
3
|
+
*
|
|
4
|
+
* What agents can do: find designs, create a blank design (preset type or
|
|
5
|
+
* custom size, optionally from an uploaded asset), export a design
|
|
6
|
+
* (PDF / PNG / JPG / PPTX / GIF / MP4 — an async job, polled here to a
|
|
7
|
+
* download URL), and upload images / videos as assets. Video *generation*
|
|
8
|
+
* is not in the API: agents fill, duplicate and export, they do not render
|
|
9
|
+
* from scratch. Brand templates need Canva Enterprise and are not wired.
|
|
10
|
+
*
|
|
11
|
+
* @module services/canva/canva.service
|
|
12
|
+
*/
|
|
13
|
+
/** Token provider slice. */
|
|
14
|
+
export interface CanvaTokenProvider {
|
|
15
|
+
getAccessToken(): Promise<string>;
|
|
16
|
+
clearCache(): void;
|
|
17
|
+
}
|
|
18
|
+
/** Service dependencies. */
|
|
19
|
+
export interface CanvaApiDeps {
|
|
20
|
+
tokens: CanvaTokenProvider;
|
|
21
|
+
fetchImpl?: typeof fetch;
|
|
22
|
+
/** Sleep between job polls (injectable for tests). */
|
|
23
|
+
sleep?: (ms: number) => Promise<void>;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
}
|
|
26
|
+
/** A design, trimmed. */
|
|
27
|
+
export interface CanvaDesign {
|
|
28
|
+
id: string;
|
|
29
|
+
title: string;
|
|
30
|
+
editUrl?: string;
|
|
31
|
+
viewUrl?: string;
|
|
32
|
+
thumbnailUrl?: string;
|
|
33
|
+
pageCount?: number;
|
|
34
|
+
createdAt?: string;
|
|
35
|
+
updatedAt?: string;
|
|
36
|
+
}
|
|
37
|
+
/** List input. */
|
|
38
|
+
export interface CanvaListInput {
|
|
39
|
+
query?: string;
|
|
40
|
+
ownership?: 'any' | 'owned' | 'shared';
|
|
41
|
+
sortBy?: 'relevance' | 'modified_descending' | 'modified_ascending' | 'title_descending' | 'title_ascending';
|
|
42
|
+
limit?: number;
|
|
43
|
+
continuation?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Create input. */
|
|
46
|
+
export interface CanvaCreateInput {
|
|
47
|
+
title?: string;
|
|
48
|
+
/** `doc` | `whiteboard` | `presentation` */
|
|
49
|
+
preset?: string;
|
|
50
|
+
/** Custom size in px (40–8000) */
|
|
51
|
+
width?: number;
|
|
52
|
+
height?: number;
|
|
53
|
+
/** Start from an uploaded asset (image) */
|
|
54
|
+
assetId?: string;
|
|
55
|
+
}
|
|
56
|
+
/** Export input. */
|
|
57
|
+
export interface CanvaExportInput {
|
|
58
|
+
designId: string;
|
|
59
|
+
format: string;
|
|
60
|
+
/** JPG quality 1–100 (default 80) */
|
|
61
|
+
quality?: number;
|
|
62
|
+
/** MP4 quality preset, e.g. `horizontal_1080p` (default) */
|
|
63
|
+
videoQuality?: string;
|
|
64
|
+
/** Page numbers (1-based) */
|
|
65
|
+
pages?: number[];
|
|
66
|
+
}
|
|
67
|
+
/** Export result. */
|
|
68
|
+
export interface CanvaExport {
|
|
69
|
+
jobId: string;
|
|
70
|
+
status: 'success' | 'failed' | 'in_progress';
|
|
71
|
+
/** Download URLs (short-lived), one per file */
|
|
72
|
+
urls: string[];
|
|
73
|
+
error?: {
|
|
74
|
+
code?: string;
|
|
75
|
+
message?: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** An uploaded asset. */
|
|
79
|
+
export interface CanvaAsset {
|
|
80
|
+
id: string;
|
|
81
|
+
name: string;
|
|
82
|
+
thumbnailUrl?: string;
|
|
83
|
+
createdAt?: string;
|
|
84
|
+
}
|
|
85
|
+
interface WireDesign {
|
|
86
|
+
id?: string;
|
|
87
|
+
title?: string;
|
|
88
|
+
urls?: {
|
|
89
|
+
edit_url?: string;
|
|
90
|
+
view_url?: string;
|
|
91
|
+
};
|
|
92
|
+
thumbnail?: {
|
|
93
|
+
url?: string;
|
|
94
|
+
};
|
|
95
|
+
page_count?: number;
|
|
96
|
+
created_at?: number;
|
|
97
|
+
updated_at?: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Trim a Canva design resource.
|
|
101
|
+
*
|
|
102
|
+
* @param d - Wire design
|
|
103
|
+
* @returns Trimmed
|
|
104
|
+
*/
|
|
105
|
+
export declare function toDesign(d: WireDesign): CanvaDesign;
|
|
106
|
+
/**
|
|
107
|
+
* The `format` object for an export job.
|
|
108
|
+
*
|
|
109
|
+
* @param input - Export input
|
|
110
|
+
* @returns Canva format object
|
|
111
|
+
* @throws CanvaError(400, validation) for an unknown format / bad quality
|
|
112
|
+
*/
|
|
113
|
+
export declare function buildExportFormat(input: CanvaExportInput): Record<string, unknown>;
|
|
114
|
+
/**
|
|
115
|
+
* Canva Connect calls.
|
|
116
|
+
*/
|
|
117
|
+
export declare class CanvaService {
|
|
118
|
+
private readonly deps;
|
|
119
|
+
private readonly base;
|
|
120
|
+
/**
|
|
121
|
+
* @param deps - Token provider, fetch, sleep
|
|
122
|
+
*/
|
|
123
|
+
constructor(deps: CanvaApiDeps);
|
|
124
|
+
/**
|
|
125
|
+
* `GET /designs` — search / list.
|
|
126
|
+
*
|
|
127
|
+
* @param input - Query, ownership, sort, limit, continuation
|
|
128
|
+
* @returns Designs + continuation token
|
|
129
|
+
*/
|
|
130
|
+
listDesigns(input?: CanvaListInput): Promise<{
|
|
131
|
+
designs: CanvaDesign[];
|
|
132
|
+
continuation?: string;
|
|
133
|
+
}>;
|
|
134
|
+
/**
|
|
135
|
+
* `GET /designs/:id`.
|
|
136
|
+
*
|
|
137
|
+
* @param id - Design id
|
|
138
|
+
* @returns The design
|
|
139
|
+
*/
|
|
140
|
+
getDesign(id: string): Promise<CanvaDesign>;
|
|
141
|
+
/**
|
|
142
|
+
* `POST /designs` — a new design from a preset type, a custom size, or an asset.
|
|
143
|
+
*
|
|
144
|
+
* @param input - Title + type/size/asset
|
|
145
|
+
* @returns The new design (with editUrl)
|
|
146
|
+
* @throws CanvaError(400, validation) when neither a valid preset, size nor asset is given
|
|
147
|
+
*/
|
|
148
|
+
createDesign(input: CanvaCreateInput): Promise<CanvaDesign>;
|
|
149
|
+
/**
|
|
150
|
+
* `POST /exports` then poll `GET /exports/:id` until done.
|
|
151
|
+
*
|
|
152
|
+
* @param input - Design, format, options
|
|
153
|
+
* @returns Download URLs (or the failure)
|
|
154
|
+
*/
|
|
155
|
+
exportDesign(input: CanvaExportInput): Promise<CanvaExport>;
|
|
156
|
+
/**
|
|
157
|
+
* `POST /asset-uploads` (binary body) then poll `GET /asset-uploads/:id`.
|
|
158
|
+
*
|
|
159
|
+
* @param name - Asset name (≤ 50 chars)
|
|
160
|
+
* @param bytes - File content
|
|
161
|
+
* @returns The asset
|
|
162
|
+
* @throws CanvaError(400, validation) for an empty/oversized file; 502 when the job fails
|
|
163
|
+
*/
|
|
164
|
+
uploadAsset(name: string, bytes: Buffer): Promise<CanvaAsset>;
|
|
165
|
+
/**
|
|
166
|
+
* Poll a job until it leaves `in_progress` or the ceiling passes.
|
|
167
|
+
*
|
|
168
|
+
* @param url - Job URL
|
|
169
|
+
* @param first - The job as returned by the create call
|
|
170
|
+
* @returns The final job
|
|
171
|
+
*/
|
|
172
|
+
private pollJob;
|
|
173
|
+
/**
|
|
174
|
+
* Authenticated call; 401 drops the cached token, 403/404/429 pass
|
|
175
|
+
* through, other failures fold into 502.
|
|
176
|
+
*
|
|
177
|
+
* @param url - Absolute URL
|
|
178
|
+
* @param init - Method / body / headers
|
|
179
|
+
* @returns Parsed JSON
|
|
180
|
+
*/
|
|
181
|
+
private request;
|
|
182
|
+
}
|
|
183
|
+
export {};
|
|
184
|
+
//# sourceMappingURL=canva.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canva.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/canva/canva.service.ts"],"names":[],"mappings":"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"}
|