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.
Files changed (114) hide show
  1. package/config/skills/agent/core/canva-create/SKILL.md +53 -0
  2. package/config/skills/agent/core/canva-create/execute.sh +88 -0
  3. package/config/skills/agent/core/canva-create/execute.test.sh +54 -0
  4. package/config/skills/agent/core/canva-designs/SKILL.md +51 -0
  5. package/config/skills/agent/core/canva-designs/execute.sh +96 -0
  6. package/config/skills/agent/core/canva-designs/execute.test.sh +54 -0
  7. package/config/skills/agent/core/canva-export/SKILL.md +52 -0
  8. package/config/skills/agent/core/canva-export/execute.sh +111 -0
  9. package/config/skills/agent/core/canva-export/execute.test.sh +55 -0
  10. package/config/skills/agent/core/canva-upload/SKILL.md +49 -0
  11. package/config/skills/agent/core/canva-upload/execute.sh +72 -0
  12. package/config/skills/agent/core/canva-upload/execute.test.sh +54 -0
  13. package/config/skills/agent/core/docs-read/SKILL.md +50 -0
  14. package/config/skills/agent/core/docs-read/execute.sh +68 -0
  15. package/config/skills/agent/core/docs-read/execute.test.sh +52 -0
  16. package/config/skills/agent/core/docs-write/SKILL.md +55 -0
  17. package/config/skills/agent/core/docs-write/execute.sh +90 -0
  18. package/config/skills/agent/core/docs-write/execute.test.sh +54 -0
  19. package/config/skills/agent/core/drive-read/SKILL.md +53 -0
  20. package/config/skills/agent/core/drive-read/execute.sh +79 -0
  21. package/config/skills/agent/core/drive-read/execute.test.sh +55 -0
  22. package/config/skills/agent/core/drive-search/SKILL.md +55 -0
  23. package/config/skills/agent/core/drive-search/execute.sh +87 -0
  24. package/config/skills/agent/core/drive-search/execute.test.sh +54 -0
  25. package/config/skills/agent/core/drive-upload/SKILL.md +54 -0
  26. package/config/skills/agent/core/drive-upload/execute.sh +117 -0
  27. package/config/skills/agent/core/drive-upload/execute.test.sh +57 -0
  28. package/config/skills/agent/core/sheets-read/SKILL.md +53 -0
  29. package/config/skills/agent/core/sheets-read/execute.sh +81 -0
  30. package/config/skills/agent/core/sheets-read/execute.test.sh +52 -0
  31. package/config/skills/agent/core/sheets-write/SKILL.md +56 -0
  32. package/config/skills/agent/core/sheets-write/execute.sh +103 -0
  33. package/config/skills/agent/core/sheets-write/execute.test.sh +57 -0
  34. package/config/skills/agent/core/slides-create/SKILL.md +61 -0
  35. package/config/skills/agent/core/slides-create/execute.sh +92 -0
  36. package/config/skills/agent/core/slides-create/execute.test.sh +54 -0
  37. package/config/skills/agent/core/slides-read/SKILL.md +49 -0
  38. package/config/skills/agent/core/slides-read/execute.sh +67 -0
  39. package/config/skills/agent/core/slides-read/execute.test.sh +50 -0
  40. package/dist/backend/backend/src/constants.d.ts +69 -0
  41. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  42. package/dist/backend/backend/src/constants.js +73 -0
  43. package/dist/backend/backend/src/constants.js.map +1 -1
  44. package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts +48 -0
  45. package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts.map +1 -0
  46. package/dist/backend/backend/src/controllers/canva/canva.controller.js +183 -0
  47. package/dist/backend/backend/src/controllers/canva/canva.controller.js.map +1 -0
  48. package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts +22 -0
  49. package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -0
  50. package/dist/backend/backend/src/controllers/canva/canva.routes.js +34 -0
  51. package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -0
  52. package/dist/backend/backend/src/controllers/google/google.controller.d.ts +100 -0
  53. package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
  54. package/dist/backend/backend/src/controllers/google/google.controller.js +237 -1
  55. package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
  56. package/dist/backend/backend/src/controllers/google/google.routes.d.ts +13 -0
  57. package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
  58. package/dist/backend/backend/src/controllers/google/google.routes.js +27 -1
  59. package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
  60. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  61. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  62. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  63. package/dist/backend/backend/src/services/canva/canva-token.service.d.ts +98 -0
  64. package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -0
  65. package/dist/backend/backend/src/services/canva/canva-token.service.js +198 -0
  66. package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -0
  67. package/dist/backend/backend/src/services/canva/canva.service.d.ts +184 -0
  68. package/dist/backend/backend/src/services/canva/canva.service.d.ts.map +1 -0
  69. package/dist/backend/backend/src/services/canva/canva.service.js +274 -0
  70. package/dist/backend/backend/src/services/canva/canva.service.js.map +1 -0
  71. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +2 -2
  72. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  73. package/dist/backend/backend/src/services/google/docs.service.d.ts +117 -0
  74. package/dist/backend/backend/src/services/google/docs.service.d.ts.map +1 -0
  75. package/dist/backend/backend/src/services/google/docs.service.js +152 -0
  76. package/dist/backend/backend/src/services/google/docs.service.js.map +1 -0
  77. package/dist/backend/backend/src/services/google/drive.service.d.ts +157 -0
  78. package/dist/backend/backend/src/services/google/drive.service.d.ts.map +1 -0
  79. package/dist/backend/backend/src/services/google/drive.service.js +203 -0
  80. package/dist/backend/backend/src/services/google/drive.service.js.map +1 -0
  81. package/dist/backend/backend/src/services/google/google-api.client.d.ts +15 -7
  82. package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
  83. package/dist/backend/backend/src/services/google/google-api.client.js +13 -6
  84. package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
  85. package/dist/backend/backend/src/services/google/sheets.service.d.ts +118 -0
  86. package/dist/backend/backend/src/services/google/sheets.service.d.ts.map +1 -0
  87. package/dist/backend/backend/src/services/google/sheets.service.js +158 -0
  88. package/dist/backend/backend/src/services/google/sheets.service.js.map +1 -0
  89. package/dist/backend/backend/src/services/google/slides.service.d.ts +136 -0
  90. package/dist/backend/backend/src/services/google/slides.service.d.ts.map +1 -0
  91. package/dist/backend/backend/src/services/google/slides.service.js +153 -0
  92. package/dist/backend/backend/src/services/google/slides.service.js.map +1 -0
  93. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  94. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +16 -3
  95. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  96. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  97. package/dist/backend/backend/src/services/slack/slack.service.js +11 -7
  98. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  99. package/dist/backend/build-info.json +2 -2
  100. package/dist/cli/backend/src/constants.d.ts +69 -0
  101. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  102. package/dist/cli/backend/src/constants.js +73 -0
  103. package/dist/cli/backend/src/constants.js.map +1 -1
  104. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +2 -2
  105. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  106. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  107. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +16 -3
  108. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  109. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  110. package/dist/cli/backend/src/services/slack/slack.service.js +11 -7
  111. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  112. package/frontend/dist/assets/{index-d1bd0dec.js → index-96b51cd9.js} +243 -243
  113. package/frontend/dist/index.html +1 -1
  114. package/package.json +1 -1
@@ -26,19 +26,27 @@ export interface GoogleApiDeps {
26
26
  * @returns The full URL string
27
27
  */
28
28
  export declare function buildGoogleUrl(base: string, params?: Record<string, string | number | string[] | undefined>): string;
29
+ /** Request options for {@link googleRequest}. */
30
+ export interface GoogleRequestInit {
31
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
32
+ /** JSON body (serialised, `Content-Type: application/json`). */
33
+ body?: unknown;
34
+ /** Pre-encoded body (multipart upload, binary) — needs `contentType`. */
35
+ rawBody?: string | Buffer;
36
+ contentType?: string;
37
+ /** `text` returns the body verbatim (Drive export / `alt=media`); default `json`. */
38
+ responseType?: 'json' | 'text';
39
+ }
29
40
  /**
30
- * Authenticated JSON call to a Google API.
41
+ * Authenticated call to a Google API.
31
42
  *
32
43
  * @param deps - Token provider + fetch
33
44
  * @param url - Absolute URL (use {@link buildGoogleUrl})
34
- * @param init - Method and optional JSON body
35
- * @returns The parsed JSON response
45
+ * @param init - Method, body and response type
46
+ * @returns The parsed JSON response (or the raw text with `responseType: 'text'`)
36
47
  * @throws GoogleWorkspaceError — token failures pass through; Google 401 →
37
48
  * 401 google_error (cache dropped), 403/404/429 keep their status, other
38
49
  * failures → 502 google_error, unreachable → 502 network
39
50
  */
40
- export declare function googleRequest<T>(deps: GoogleApiDeps, url: string, init?: {
41
- method?: 'GET' | 'POST';
42
- body?: unknown;
43
- }): Promise<T>;
51
+ export declare function googleRequest<T>(deps: GoogleApiDeps, url: string, init?: GoogleRequestInit): Promise<T>;
44
52
  //# sourceMappingURL=google-api.client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-api.client.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-api.client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,yEAAyE;AACzE,MAAM,WAAW,mBAAmB;IAClC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAwBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,GAAG,MAAM,CAWxH;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GACrD,OAAO,CAAC,CAAC,CAAC,CAsCZ"}
1
+ {"version":3,"file":"google-api.client.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-api.client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,yEAAyE;AACzE,MAAM,WAAW,mBAAmB;IAClC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAwBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,GAAG,MAAM,CAWxH;AAED,iDAAiD;AACjD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrD,gEAAgE;IAChE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,CAAC,CAAC,CA4CjH"}
@@ -51,12 +51,12 @@ export function buildGoogleUrl(base, params = {}) {
51
51
  return url.toString();
52
52
  }
53
53
  /**
54
- * Authenticated JSON call to a Google API.
54
+ * Authenticated call to a Google API.
55
55
  *
56
56
  * @param deps - Token provider + fetch
57
57
  * @param url - Absolute URL (use {@link buildGoogleUrl})
58
- * @param init - Method and optional JSON body
59
- * @returns The parsed JSON response
58
+ * @param init - Method, body and response type
59
+ * @returns The parsed JSON response (or the raw text with `responseType: 'text'`)
60
60
  * @throws GoogleWorkspaceError — token failures pass through; Google 401 →
61
61
  * 401 google_error (cache dropped), 403/404/429 keep their status, other
62
62
  * failures → 502 google_error, unreachable → 502 network
@@ -65,16 +65,21 @@ export async function googleRequest(deps, url, init = {}) {
65
65
  const token = await deps.tokens.getAccessToken();
66
66
  const fetchImpl = deps.fetchImpl ?? fetch;
67
67
  const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
68
+ const wantsText = init.responseType === 'text';
68
69
  let res;
69
70
  try {
70
71
  res = await fetchImpl(url, {
71
72
  method: init.method ?? 'GET',
72
73
  headers: {
73
74
  Authorization: `Bearer ${token}`,
74
- Accept: 'application/json',
75
- ...(init.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
75
+ Accept: wantsText ? '*/*' : 'application/json',
76
+ ...(init.rawBody !== undefined
77
+ ? { 'Content-Type': init.contentType ?? 'application/octet-stream' }
78
+ : init.body !== undefined
79
+ ? { 'Content-Type': 'application/json' }
80
+ : {}),
76
81
  },
77
- body: init.body !== undefined ? JSON.stringify(init.body) : undefined,
82
+ body: init.rawBody !== undefined ? init.rawBody : init.body !== undefined ? JSON.stringify(init.body) : undefined,
78
83
  signal: AbortSignal.timeout(GOOGLE_WORKSPACE_CONSTANTS.REQUEST_TIMEOUT_MS),
79
84
  });
80
85
  }
@@ -92,6 +97,8 @@ export async function googleRequest(deps, url, init = {}) {
92
97
  const passthrough = res.status === 403 || res.status === 404 || res.status === 429;
93
98
  throw new GoogleWorkspaceError(passthrough ? res.status : 502, CODES.GOOGLE_ERROR, message);
94
99
  }
100
+ if (wantsText)
101
+ return text;
95
102
  if (!text)
96
103
  return {};
97
104
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"google-api.client.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-api.client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAmB3E;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;QACnD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC;QAC1D,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,SAAiE,EAAE;IAC9G,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,SAAS;QAClD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,IAAI,KAAK;gBAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAmB,EACnB,GAAW,EACX,OAAoD,EAAE;IAEtD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAC1C,MAAM,KAAK,GAAG,0BAA0B,CAAC,WAAW,CAAC;IAErD,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;YAC5B,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,MAAM,EAAE,kBAAkB;gBAC1B,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3E;YACD,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YACrE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,0BAA0B,CAAC,kBAAkB,CAAC;SAC3E,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,uBAAuB,OAAO,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,0BAA0B,GAAG,CAAC,MAAM,GAAG,CAAC;QACpF,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACzB,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY,EAAE,qCAAqC,OAAO,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC;QACnF,MAAM,IAAI,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAO,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY,EAAE,sCAAsC,CAAC,CAAC;IAClG,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"google-api.client.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-api.client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * SheetsService — Google Sheets over the owner's Workspace grant.
3
+ *
4
+ * Reads any spreadsheet the owner can see (`drive.readonly`), creates new
5
+ * spreadsheets and writes to the ones Crewly created (`drive.file`).
6
+ * Writing to a spreadsheet made elsewhere needs the `spreadsheets` scope
7
+ * the grant does not carry yet; Google answers 403 and the error says so.
8
+ *
9
+ * @module services/google/sheets.service
10
+ */
11
+ import { type GoogleApiDeps } from './google-api.client.js';
12
+ /** A cell value as the API returns it (strings/numbers/booleans). */
13
+ export type SheetCell = string | number | boolean;
14
+ /** A rectangular block of values. */
15
+ export interface SheetValues {
16
+ spreadsheetId: string;
17
+ range: string;
18
+ rows: SheetCell[][];
19
+ }
20
+ /** Spreadsheet metadata. */
21
+ export interface SpreadsheetInfo {
22
+ id: string;
23
+ title: string;
24
+ sheets: Array<{
25
+ title: string;
26
+ rowCount?: number;
27
+ columnCount?: number;
28
+ }>;
29
+ webViewLink: string;
30
+ }
31
+ /** Create input. */
32
+ export interface SheetCreateInput {
33
+ title: string;
34
+ /** Name of the first sheet tab (default "Sheet1"). */
35
+ sheetTitle?: string;
36
+ /** Initial rows written from A1. */
37
+ rows?: SheetCell[][];
38
+ }
39
+ /** Write input (append or overwrite). */
40
+ export interface SheetWriteInput {
41
+ spreadsheetId: string;
42
+ /** A1 range; for append the table it belongs to, for update the top-left anchor. */
43
+ range?: string;
44
+ rows: SheetCell[][];
45
+ }
46
+ /**
47
+ * Validate rows for a write.
48
+ *
49
+ * @param rows - Candidate rows
50
+ * @returns The rows
51
+ * @throws GoogleWorkspaceError(400, validation) when empty, not rectangular-ish, or too many
52
+ */
53
+ export declare function requireRows(rows: unknown): SheetCell[][];
54
+ /**
55
+ * Sheets: read, create, append, update.
56
+ */
57
+ export declare class SheetsService {
58
+ private readonly deps;
59
+ private readonly base;
60
+ /**
61
+ * @param deps - Token provider and optional fetch override
62
+ */
63
+ constructor(deps: GoogleApiDeps);
64
+ /**
65
+ * `spreadsheets.get` (properties only) — title and the sheet tabs.
66
+ *
67
+ * @param id - Spreadsheet id
68
+ * @returns Metadata
69
+ */
70
+ info(id: string): Promise<SpreadsheetInfo>;
71
+ /**
72
+ * `spreadsheets.values.get`.
73
+ *
74
+ * @param id - Spreadsheet id
75
+ * @param range - A1 range (default `A1:Z1000` on the first sheet)
76
+ * @returns The values (rows may be ragged)
77
+ */
78
+ read(id: string, range?: string): Promise<SheetValues>;
79
+ /**
80
+ * `spreadsheets.create`, then `values.update` from A1 when rows are given.
81
+ *
82
+ * @param input - Title, first-sheet name, initial rows
83
+ * @returns The new spreadsheet
84
+ * @throws GoogleWorkspaceError(400, validation) without a title
85
+ */
86
+ create(input: SheetCreateInput): Promise<SpreadsheetInfo>;
87
+ /**
88
+ * `spreadsheets.values.append` — rows go below the last row of the
89
+ * table that contains `range` (default: the first sheet).
90
+ *
91
+ * @param input - Spreadsheet, range, rows
92
+ * @returns Updated range and counts
93
+ */
94
+ append(input: SheetWriteInput): Promise<{
95
+ spreadsheetId: string;
96
+ updatedRange: string;
97
+ updatedRows: number;
98
+ }>;
99
+ /**
100
+ * `spreadsheets.values.update` — overwrite starting at `range`.
101
+ *
102
+ * @param input - Spreadsheet, anchor range, rows
103
+ * @returns Updated range and counts
104
+ */
105
+ update(input: SheetWriteInput): Promise<{
106
+ spreadsheetId: string;
107
+ updatedRange: string;
108
+ updatedRows: number;
109
+ }>;
110
+ }
111
+ /**
112
+ * Quote a sheet name for an A1 range when it needs it.
113
+ *
114
+ * @param name - Sheet title
115
+ * @returns `'My Sheet'` or `Sheet1`
116
+ */
117
+ export declare function quoteSheet(name: string): string;
118
+ //# sourceMappingURL=sheets.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheets.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/sheets.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAiC,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG3F,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAElD,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;CACrB;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oBAAoB;AACpB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC;CACtB;AAED,yCAAyC;AACzC,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;CACrB;AASD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,EAAE,EAAE,CAexD;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8C;IAEnE;;OAEG;gBACS,IAAI,EAAE,aAAa;IAI/B;;;;;OAKG;IACG,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAWhD;;;;;;OAMG;IACG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAa5D;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAe/D;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAenH;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAapH;AAgBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * SheetsService — Google Sheets over the owner's Workspace grant.
3
+ *
4
+ * Reads any spreadsheet the owner can see (`drive.readonly`), creates new
5
+ * spreadsheets and writes to the ones Crewly created (`drive.file`).
6
+ * Writing to a spreadsheet made elsewhere needs the `spreadsheets` scope
7
+ * the grant does not carry yet; Google answers 403 and the error says so.
8
+ *
9
+ * @module services/google/sheets.service
10
+ */
11
+ import { GOOGLE_WORKSPACE_CONSTANTS } from '../../constants.js';
12
+ import { GoogleWorkspaceError } from './google-workspace-token.service.js';
13
+ import { buildGoogleUrl, googleRequest } from './google-api.client.js';
14
+ import { requireId } from './drive.service.js';
15
+ /**
16
+ * Validate rows for a write.
17
+ *
18
+ * @param rows - Candidate rows
19
+ * @returns The rows
20
+ * @throws GoogleWorkspaceError(400, validation) when empty, not rectangular-ish, or too many
21
+ */
22
+ export function requireRows(rows) {
23
+ const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
24
+ if (!Array.isArray(rows) || rows.length === 0)
25
+ throw new GoogleWorkspaceError(400, CODES.VALIDATION, '"rows" must be a non-empty array of arrays');
26
+ if (rows.length > GOOGLE_WORKSPACE_CONSTANTS.SHEETS_MAX_ROWS) {
27
+ throw new GoogleWorkspaceError(400, CODES.VALIDATION, `"rows" exceeds ${GOOGLE_WORKSPACE_CONSTANTS.SHEETS_MAX_ROWS}`);
28
+ }
29
+ for (const row of rows) {
30
+ if (!Array.isArray(row))
31
+ throw new GoogleWorkspaceError(400, CODES.VALIDATION, 'each row must be an array');
32
+ for (const cell of row) {
33
+ if (cell !== null && cell !== undefined && !['string', 'number', 'boolean'].includes(typeof cell)) {
34
+ throw new GoogleWorkspaceError(400, CODES.VALIDATION, 'cells must be strings, numbers or booleans');
35
+ }
36
+ }
37
+ }
38
+ return rows.map((row) => row.map((cell) => (cell === null || cell === undefined ? '' : cell)));
39
+ }
40
+ /**
41
+ * Sheets: read, create, append, update.
42
+ */
43
+ export class SheetsService {
44
+ deps;
45
+ base = GOOGLE_WORKSPACE_CONSTANTS.SHEETS_API_BASE;
46
+ /**
47
+ * @param deps - Token provider and optional fetch override
48
+ */
49
+ constructor(deps) {
50
+ this.deps = deps;
51
+ }
52
+ /**
53
+ * `spreadsheets.get` (properties only) — title and the sheet tabs.
54
+ *
55
+ * @param id - Spreadsheet id
56
+ * @returns Metadata
57
+ */
58
+ async info(id) {
59
+ const spreadsheetId = requireId(id);
60
+ const wire = await googleRequest(this.deps, buildGoogleUrl(`${this.base}/spreadsheets/${encodeURIComponent(spreadsheetId)}`, {
61
+ fields: 'spreadsheetId,properties.title,spreadsheetUrl,sheets.properties(title,gridProperties(rowCount,columnCount))',
62
+ }));
63
+ return toInfo(wire);
64
+ }
65
+ /**
66
+ * `spreadsheets.values.get`.
67
+ *
68
+ * @param id - Spreadsheet id
69
+ * @param range - A1 range (default `A1:Z1000` on the first sheet)
70
+ * @returns The values (rows may be ragged)
71
+ */
72
+ async read(id, range) {
73
+ const spreadsheetId = requireId(id);
74
+ const a1 = (range ?? '').trim() || GOOGLE_WORKSPACE_CONSTANTS.SHEETS_DEFAULT_RANGE;
75
+ const data = await googleRequest(this.deps, buildGoogleUrl(`${this.base}/spreadsheets/${encodeURIComponent(spreadsheetId)}/values/${encodeURIComponent(a1)}`, {
76
+ valueRenderOption: 'UNFORMATTED_VALUE',
77
+ dateTimeRenderOption: 'FORMATTED_STRING',
78
+ }));
79
+ return { spreadsheetId, range: data.range ?? a1, rows: data.values ?? [] };
80
+ }
81
+ /**
82
+ * `spreadsheets.create`, then `values.update` from A1 when rows are given.
83
+ *
84
+ * @param input - Title, first-sheet name, initial rows
85
+ * @returns The new spreadsheet
86
+ * @throws GoogleWorkspaceError(400, validation) without a title
87
+ */
88
+ async create(input) {
89
+ const title = (input.title ?? '').trim();
90
+ if (!title)
91
+ throw new GoogleWorkspaceError(400, GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES.VALIDATION, '"title" is required');
92
+ const sheetTitle = (input.sheetTitle ?? '').trim() || 'Sheet1';
93
+ const created = await googleRequest(this.deps, `${this.base}/spreadsheets`, {
94
+ method: 'POST',
95
+ body: { properties: { title }, sheets: [{ properties: { title: sheetTitle } }] },
96
+ });
97
+ const id = created.spreadsheetId ?? '';
98
+ if (input.rows && input.rows.length > 0) {
99
+ await this.update({ spreadsheetId: id, range: `${quoteSheet(sheetTitle)}!A1`, rows: input.rows });
100
+ }
101
+ return toInfo(created);
102
+ }
103
+ /**
104
+ * `spreadsheets.values.append` — rows go below the last row of the
105
+ * table that contains `range` (default: the first sheet).
106
+ *
107
+ * @param input - Spreadsheet, range, rows
108
+ * @returns Updated range and counts
109
+ */
110
+ async append(input) {
111
+ const spreadsheetId = requireId(input.spreadsheetId);
112
+ const rows = requireRows(input.rows);
113
+ const a1 = (input.range ?? '').trim() || 'A1';
114
+ const data = await googleRequest(this.deps, buildGoogleUrl(`${this.base}/spreadsheets/${encodeURIComponent(spreadsheetId)}/values/${encodeURIComponent(a1)}:append`, {
115
+ valueInputOption: 'USER_ENTERED',
116
+ insertDataOption: 'INSERT_ROWS',
117
+ }), { method: 'POST', body: { values: rows } });
118
+ return { spreadsheetId, updatedRange: data.updates?.updatedRange ?? a1, updatedRows: data.updates?.updatedRows ?? rows.length };
119
+ }
120
+ /**
121
+ * `spreadsheets.values.update` — overwrite starting at `range`.
122
+ *
123
+ * @param input - Spreadsheet, anchor range, rows
124
+ * @returns Updated range and counts
125
+ */
126
+ async update(input) {
127
+ const spreadsheetId = requireId(input.spreadsheetId);
128
+ const rows = requireRows(input.rows);
129
+ const a1 = (input.range ?? '').trim() || 'A1';
130
+ const data = await googleRequest(this.deps, buildGoogleUrl(`${this.base}/spreadsheets/${encodeURIComponent(spreadsheetId)}/values/${encodeURIComponent(a1)}`, {
131
+ valueInputOption: 'USER_ENTERED',
132
+ }), { method: 'PUT', body: { values: rows } });
133
+ return { spreadsheetId, updatedRange: data.updatedRange ?? a1, updatedRows: data.updatedRows ?? rows.length };
134
+ }
135
+ }
136
+ function toInfo(wire) {
137
+ const id = wire.spreadsheetId ?? '';
138
+ return {
139
+ id,
140
+ title: wire.properties?.title ?? '',
141
+ sheets: (wire.sheets ?? []).map((s) => ({
142
+ title: s.properties?.title ?? '',
143
+ ...(s.properties?.gridProperties?.rowCount !== undefined ? { rowCount: s.properties.gridProperties.rowCount } : {}),
144
+ ...(s.properties?.gridProperties?.columnCount !== undefined ? { columnCount: s.properties.gridProperties.columnCount } : {}),
145
+ })),
146
+ webViewLink: wire.spreadsheetUrl ?? `https://docs.google.com/spreadsheets/d/${id}/edit`,
147
+ };
148
+ }
149
+ /**
150
+ * Quote a sheet name for an A1 range when it needs it.
151
+ *
152
+ * @param name - Sheet title
153
+ * @returns `'My Sheet'` or `Sheet1`
154
+ */
155
+ export function quoteSheet(name) {
156
+ return /^[A-Za-z0-9_]+$/.test(name) ? name : `'${name.replace(/'/g, "''")}'`;
157
+ }
158
+ //# sourceMappingURL=sheets.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheets.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/sheets.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * SlidesService — Google Slides over the owner's Workspace grant.
3
+ *
4
+ * Reads any presentation the owner can see (`drive.readonly`) and builds
5
+ * new decks from an outline (`drive.file`). Each outline slide becomes a
6
+ * TITLE_AND_BODY slide with the title and bullet lines; the deck's default
7
+ * first slide is removed so the outline is the whole deck.
8
+ *
9
+ * @module services/google/slides.service
10
+ */
11
+ import { type GoogleApiDeps } from './google-api.client.js';
12
+ /** One slide, flattened. */
13
+ export interface SlideText {
14
+ index: number;
15
+ objectId: string;
16
+ /** Every text line on the slide, in reading order. */
17
+ lines: string[];
18
+ notes?: string;
19
+ }
20
+ /** A presentation, flattened. */
21
+ export interface PresentationText {
22
+ id: string;
23
+ title: string;
24
+ slideCount: number;
25
+ slides: SlideText[];
26
+ webViewLink: string;
27
+ }
28
+ /** One slide of an outline. */
29
+ export interface SlideOutline {
30
+ title: string;
31
+ /** Body lines; each becomes one paragraph (bulleting is the layout's default). */
32
+ bullets?: string[];
33
+ /** Speaker notes are not written (the Slides API needs the notes shape id) — kept for callers' bookkeeping. */
34
+ notes?: string;
35
+ }
36
+ /** Create input. */
37
+ export interface PresentationCreateInput {
38
+ title: string;
39
+ slides: SlideOutline[];
40
+ }
41
+ interface WireTextElement {
42
+ textRun?: {
43
+ content?: string;
44
+ };
45
+ }
46
+ interface WirePageElement {
47
+ shape?: {
48
+ text?: {
49
+ textElements?: WireTextElement[];
50
+ };
51
+ };
52
+ table?: {
53
+ tableRows?: Array<{
54
+ tableCells?: Array<{
55
+ text?: {
56
+ textElements?: WireTextElement[];
57
+ };
58
+ }>;
59
+ }>;
60
+ };
61
+ elementGroup?: {
62
+ children?: WirePageElement[];
63
+ };
64
+ }
65
+ interface WirePage {
66
+ objectId?: string;
67
+ pageElements?: WirePageElement[];
68
+ slideProperties?: {
69
+ notesPage?: {
70
+ pageElements?: WirePageElement[];
71
+ };
72
+ };
73
+ }
74
+ interface WirePresentation {
75
+ presentationId?: string;
76
+ title?: string;
77
+ slides?: WirePage[];
78
+ }
79
+ /**
80
+ * Lines of text in a page element (shape text, table cells, groups).
81
+ *
82
+ * @param el - Page element
83
+ * @returns Non-empty lines
84
+ */
85
+ export declare function elementLines(el: WirePageElement): string[];
86
+ /**
87
+ * Flatten a presentation.
88
+ *
89
+ * @param wire - `presentations.get` payload
90
+ * @returns Title + slides as text
91
+ */
92
+ export declare function toPresentationText(wire: WirePresentation): PresentationText;
93
+ /**
94
+ * The batchUpdate requests that turn an outline into slides.
95
+ *
96
+ * @param outline - Slides to add
97
+ * @param removeSlideId - Object id of the default slide to delete, if any
98
+ * @returns Requests in order (creates, inserts, then the delete)
99
+ */
100
+ export declare function buildSlideRequests(outline: SlideOutline[], removeSlideId?: string): unknown[];
101
+ /**
102
+ * Slides: read, create from outline.
103
+ */
104
+ export declare class SlidesService {
105
+ private readonly deps;
106
+ private readonly base;
107
+ /**
108
+ * @param deps - Token provider and optional fetch override
109
+ */
110
+ constructor(deps: GoogleApiDeps);
111
+ /**
112
+ * `presentations.get`, flattened to text per slide.
113
+ *
114
+ * @param id - Presentation id
115
+ * @returns Title + slides
116
+ */
117
+ read(id: string): Promise<PresentationText>;
118
+ /**
119
+ * `presentations.create` + one `batchUpdate` that adds every outline
120
+ * slide and removes the default blank one.
121
+ *
122
+ * @param input - Title and outline
123
+ * @returns The new deck, flattened (as read back from Google)
124
+ * @throws GoogleWorkspaceError(400, validation) without a title / slides, or too many slides
125
+ */
126
+ create(input: PresentationCreateInput): Promise<PresentationText>;
127
+ }
128
+ /**
129
+ * Browser link for a presentation.
130
+ *
131
+ * @param id - Presentation id
132
+ * @returns URL
133
+ */
134
+ export declare function slidesLink(id: string): string;
135
+ export {};
136
+ //# sourceMappingURL=slides.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slides.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/slides.service.ts"],"names":[],"mappings":"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"}