@pipedream/google_drive 3.0.1 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/actions/add-comment/add-comment.mjs +1 -1
  2. package/actions/add-file-sharing-preference/add-file-sharing-preference.mjs +1 -1
  3. package/actions/copy-file/copy-file.mjs +1 -1
  4. package/actions/create-file-from-template/create-file-from-template.mjs +1 -1
  5. package/actions/create-file-from-text/create-file-from-text.mjs +1 -1
  6. package/actions/create-folder/create-folder.mjs +1 -1
  7. package/actions/create-shared-drive/create-shared-drive.mjs +1 -1
  8. package/actions/create-text-file/create-text-file.mjs +1 -1
  9. package/actions/delete-comment/delete-comment.mjs +1 -1
  10. package/actions/delete-file/delete-file.mjs +1 -1
  11. package/actions/delete-reply/delete-reply.mjs +1 -1
  12. package/actions/delete-shared-drive/delete-shared-drive.mjs +1 -1
  13. package/actions/download-file/download-file.mjs +26 -7
  14. package/actions/find-file/find-file.mjs +1 -1
  15. package/actions/find-folder/find-folder.mjs +1 -1
  16. package/actions/find-forms/find-forms.mjs +1 -1
  17. package/actions/find-spreadsheets/find-spreadsheets.mjs +1 -1
  18. package/actions/get-comment/get-comment.mjs +1 -1
  19. package/actions/get-current-user/get-current-user.mjs +1 -1
  20. package/actions/get-file/get-file.mjs +1 -1
  21. package/actions/get-file-by-id/get-file-by-id.mjs +1 -1
  22. package/actions/get-folder-id-for-path/get-folder-id-for-path.mjs +1 -1
  23. package/actions/get-reply/get-reply.mjs +1 -1
  24. package/actions/get-shared-drive/get-shared-drive.mjs +1 -1
  25. package/actions/get-user-details/get-user-details.mjs +1 -1
  26. package/actions/is-folder-ancestor/is-folder-ancestor.mjs +1 -1
  27. package/actions/list-access-proposals/list-access-proposals.mjs +1 -1
  28. package/actions/list-comments/list-comments.mjs +1 -1
  29. package/actions/list-files/list-files.mjs +1 -1
  30. package/actions/list-mime-type-options/list-mime-type-options.mjs +1 -1
  31. package/actions/list-permissions/list-permissions.mjs +1 -1
  32. package/actions/list-replies/list-replies.mjs +1 -1
  33. package/actions/list-shared-drives/list-shared-drives.mjs +1 -1
  34. package/actions/list-theme-id-options/list-theme-id-options.mjs +1 -1
  35. package/actions/move-file/move-file.mjs +1 -1
  36. package/actions/move-file-to-trash/move-file-to-trash.mjs +1 -1
  37. package/actions/remove-file-sharing-permission/remove-file-sharing-permission.mjs +1 -1
  38. package/actions/remove-sharing/remove-sharing.mjs +1 -1
  39. package/actions/reply-to-comment/reply-to-comment.mjs +1 -1
  40. package/actions/resolve-access-proposal/resolve-access-proposal.mjs +1 -1
  41. package/actions/resolve-comment/resolve-comment.mjs +1 -1
  42. package/actions/search-files/search-files.mjs +1 -1
  43. package/actions/search-shared-drives/search-shared-drives.mjs +1 -1
  44. package/actions/share-file/share-file.mjs +1 -1
  45. package/actions/trash-file/trash-file.mjs +1 -1
  46. package/actions/update-comment/update-comment.mjs +1 -1
  47. package/actions/update-file/update-file.mjs +1 -1
  48. package/actions/update-reply/update-reply.mjs +1 -1
  49. package/actions/update-shared-drive/update-shared-drive.mjs +1 -1
  50. package/actions/upload-file/upload-file.mjs +1 -1
  51. package/common/constants.mjs +29 -0
  52. package/common/utils.mjs +32 -0
  53. package/google_drive.app.mjs +21 -6
  54. package/package.json +1 -1
  55. package/sources/changes-to-files-in-drive/changes-to-files-in-drive.mjs +1 -1
  56. package/sources/changes-to-specific-files/changes-to-specific-files.mjs +1 -1
  57. package/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs +1 -1
  58. package/sources/common-dedupe-changes.mjs +23 -12
  59. package/sources/common-webhook.mjs +12 -1
  60. package/sources/new-access-proposal/new-access-proposal.mjs +1 -1
  61. package/sources/new-files-instant/new-files-instant.mjs +1 -1
  62. package/sources/new-files-instant-polling/new-files-instant-polling.mjs +1 -1
  63. package/sources/new-files-shared-drive/new-files-shared-drive.mjs +1 -1
  64. package/sources/new-or-modified-comments/new-or-modified-comments.mjs +1 -1
  65. package/sources/new-or-modified-comments-polling/new-or-modified-comments-polling.mjs +1 -1
  66. package/sources/new-or-modified-files/new-or-modified-files.mjs +59 -42
  67. package/sources/new-or-modified-files/test-event.mjs +30 -1
  68. package/sources/new-or-modified-files-polling/new-or-modified-files-polling.mjs +1 -1
  69. package/sources/new-or-modified-folders/new-or-modified-folders.mjs +1 -1
  70. package/sources/new-or-modified-folders-polling/new-or-modified-folders-polling.mjs +1 -1
  71. package/sources/new-shared-drive/new-shared-drive.mjs +1 -1
  72. package/sources/new-spreadsheet/new-spreadsheet.mjs +1 -1
  73. package/sources/new-spreadsheet-polling/new-spreadsheet-polling.mjs +1 -1
package/common/utils.mjs CHANGED
@@ -349,6 +349,37 @@ function sanitizeFileName(name) {
349
349
  return safe;
350
350
  }
351
351
 
352
+ /**
353
+ * Minimal inline worker pool. Runs `worker` over `items` with at most `limit`
354
+ * calls in flight at any moment and returns the results in input order.
355
+ *
356
+ * @param {Array} items the items to process
357
+ * @param {Number} limit the max number of concurrent `worker` calls
358
+ * @param {Function} worker async function invoked as `worker(item, index)`
359
+ * @returns {Promise<Array>} the results, in the same order as `items`
360
+ */
361
+ async function mapWithConcurrency(items, limit, worker) {
362
+ const results = new Array(items.length);
363
+ let cursor = 0;
364
+
365
+ const runNext = async () => {
366
+ while (cursor < items.length) {
367
+ const index = cursor;
368
+ cursor += 1;
369
+ results[index] = await worker(items[index], index);
370
+ }
371
+ };
372
+
373
+ const runners = [];
374
+ const poolSize = Math.min(limit, items.length);
375
+ for (let i = 0; i < poolSize; i++) {
376
+ runners.push(runNext());
377
+ }
378
+ await Promise.allSettled(runners);
379
+
380
+ return results;
381
+ }
382
+
352
383
  async function stashFile(item, googleDrive, dir) {
353
384
  const fileMetadata = await googleDrive.getFile(item.id, {
354
385
  fields: "name,mimeType",
@@ -444,6 +475,7 @@ export {
444
475
  getFilePaths,
445
476
  getListFilesOpts,
446
477
  isMyDrive,
478
+ mapWithConcurrency,
447
479
  MY_DRIVE_VALUE,
448
480
  omitEmptyStringValues,
449
481
  parseObjectEntries,
@@ -13,6 +13,8 @@ import {
13
13
  GOOGLE_DRIVE_UPDATE_TYPES,
14
14
  GOOGLE_DRIVE_UPLOAD_TYPE_OPTIONS,
15
15
  MY_DRIVE_VALUE,
16
+ RATE_LIMIT_ERROR_REASONS,
17
+ RETRYABLE_STATUS_CODES,
16
18
  WEBHOOK_SUBSCRIPTION_EXPIRATION_TIME_MILLISECONDS,
17
19
  } from "./common/constants.mjs";
18
20
 
@@ -445,15 +447,20 @@ export default {
445
447
  * returned
446
448
  * @param {number} [pageSize=1000] - the maximum number of changes to return
447
449
  * per page
450
+ * @param {string} [fileFields] - the file fields to return for each change,
451
+ * e.g. `id,name,parents`. Defaults to the API's minimal file fields
448
452
  * @yields
449
453
  * @type {ChangesPage}
450
454
  */
451
- async *listChanges(pageToken, driveId, pageSize = 1000) {
455
+ async *listChanges(pageToken, driveId, pageSize = 1000, fileFields) {
452
456
  const drive = this.drive();
453
457
  let changeRequest = {
454
458
  pageToken,
455
459
  pageSize,
456
460
  };
461
+ if (fileFields) {
462
+ changeRequest.fields = `nextPageToken,newStartPageToken,changes(file(${fileFields}))`;
463
+ }
457
464
 
458
465
  // As with many of the methods for Google Drive, we must
459
466
  // pass a request of a different shape when we're requesting
@@ -468,7 +475,9 @@ export default {
468
475
  }
469
476
 
470
477
  while (true) {
471
- const { data } = await drive.changes.list(changeRequest);
478
+ const { data } = await this.retryWithExponentialBackoff(
479
+ () => drive.changes.list(changeRequest),
480
+ );
472
481
  const {
473
482
  changes = [],
474
483
  newStartPageToken,
@@ -1693,6 +1702,14 @@ export default {
1693
1702
  const drive = this.drive();
1694
1703
  return (await drive.accessproposals.resolve(opts)).data;
1695
1704
  },
1705
+ isRetryableError(error, statusCode) {
1706
+ if (RETRYABLE_STATUS_CODES.includes(statusCode)) {
1707
+ return true;
1708
+ }
1709
+ const errors = error.errors ?? error.response?.data?.error?.errors ?? [];
1710
+ return statusCode === 403
1711
+ && errors.some(({ reason }) => RATE_LIMIT_ERROR_REASONS.includes(reason));
1712
+ },
1696
1713
  retryWithExponentialBackoff(func, maxAttempts = 3, baseDelayS = 2) {
1697
1714
  let attempt = 0;
1698
1715
 
@@ -1700,15 +1717,13 @@ export default {
1700
1717
  try {
1701
1718
  return await func();
1702
1719
  } catch (error) {
1703
- // retry for error status 422
1704
1720
  const statusCode = error.status || error.response?.status;
1705
- if (attempt >= maxAttempts || statusCode !== 422) {
1721
+ if (attempt >= maxAttempts || !this.isRetryableError(error, statusCode)) {
1706
1722
  throw error;
1707
1723
  }
1708
1724
 
1709
- // display error message for 422 status
1710
1725
  const errorMessage = error.message || error.response?.data?.message || error.response?.statusText || "Unknown error";
1711
- console.log(`Received 422 error: ${errorMessage}. Retrying attempt ${attempt + 1}/${maxAttempts}...`);
1726
+ console.log(`Received ${statusCode} error: ${errorMessage}. Retrying attempt ${attempt + 1}/${maxAttempts}...`);
1712
1727
 
1713
1728
  const delayMs = Math.pow(baseDelayS, attempt) * 1000;
1714
1729
  await new Promise((resolve) => setTimeout(resolve, delayMs));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/google_drive",
3
- "version": "3.0.1",
3
+ "version": "4.0.1",
4
4
  "description": "Pipedream Google_drive Components",
5
5
  "main": "google_drive.app.mjs",
6
6
  "keywords": [
@@ -14,7 +14,7 @@ export default {
14
14
  key: "google_drive-changes-to-files-in-drive",
15
15
  name: "Changes to Files in Drive",
16
16
  description: "Emit new event when a change is made to one of the specified files. [See the documentation](https://developers.google.com/drive/api/v3/reference/changes/watch)",
17
- version: "0.0.15",
17
+ version: "0.0.17",
18
18
  type: "source",
19
19
  dedupe: "unique",
20
20
  props: {
@@ -16,7 +16,7 @@ export default {
16
16
  key: "google_drive-changes-to-specific-files",
17
17
  name: "Changes to Specific Files",
18
18
  description: "Watches for changes to specific files, emitting an event when a change is made to one of those files. To watch for changes to [shared drive](https://support.google.com/a/users/answer/9310351) files, use the **Changes to Specific Files (Shared Drive)** source instead.",
19
- version: "0.3.13",
19
+ version: "0.3.15",
20
20
  type: "source",
21
21
  // Dedupe events based on the "x-goog-message-number" header for the target channel:
22
22
  // https://developers.google.com/drive/api/v3/push#making-watch-requests
@@ -29,7 +29,7 @@ export default {
29
29
  key: "google_drive-changes-to-specific-files-shared-drive",
30
30
  name: "Changes to Specific Files (Shared Drive)",
31
31
  description: "Watches for changes to specific files in a shared drive, emitting an event when a change is made to one of those files",
32
- version: "0.3.15",
32
+ version: "0.3.17",
33
33
  type: "source",
34
34
  // Dedupe events based on the "x-goog-message-number" header for the target channel:
35
35
  // https://developers.google.com/drive/api/v3/push#making-watch-requests
@@ -24,29 +24,40 @@ You can change or disable this minimum interval using the prop \`Minimum Interva
24
24
  _setFileIntervals(value) {
25
25
  this.db.set("fileIntervals", value);
26
26
  },
27
- checkMinimumInterval(files) {
27
+ filterByMinimumInterval(files) {
28
28
  const interval = this.perFileInterval;
29
- if (!interval) return files;
29
+ if (!interval) {
30
+ return files;
31
+ }
30
32
 
31
- const now = Date.now();
32
- const minTimestamp = now - (interval * 1000 * 60);
33
+ const minTimestamp = Date.now() - (interval * 1000 * 60);
34
+ const savedData = this._getFileIntervals();
35
+ return files.filter(({ id }) => !savedData[id] || savedData[id] < minTimestamp);
36
+ },
37
+ recordFileEmits(fileIds) {
38
+ if (!this.perFileInterval || !fileIds.length) {
39
+ return;
40
+ }
33
41
 
42
+ const now = Date.now();
43
+ const minTimestamp = now - (this.perFileInterval * 1000 * 60);
34
44
  const savedData = this._getFileIntervals();
35
45
  Object.entries(savedData).forEach(([
36
46
  key,
37
47
  value,
38
48
  ]) => {
39
- if (value < minTimestamp) delete savedData[key];
40
- });
41
-
42
- const filteredFiles = files.filter(({ id }) => {
43
- const exists = !!savedData[id];
44
- if (!exists) {
45
- savedData[id] = now;
49
+ if (value < minTimestamp) {
50
+ delete savedData[key];
46
51
  }
47
- return !exists;
52
+ });
53
+ fileIds.forEach((id) => {
54
+ savedData[id] = now;
48
55
  });
49
56
  this._setFileIntervals(savedData);
57
+ },
58
+ checkMinimumInterval(files) {
59
+ const filteredFiles = this.filterByMinimumInterval(files);
60
+ this.recordFileEmits(filteredFiles.map(({ id }) => id));
50
61
  return filteredFiles;
51
62
  },
52
63
  },
@@ -122,6 +122,12 @@ export default {
122
122
  getUpdateTypes() {
123
123
  return [];
124
124
  },
125
+ /**
126
+ * File fields to request per change; `undefined` returns the API's minimal fields.
127
+ */
128
+ getChangesFileFields() {
129
+ return undefined;
130
+ },
125
131
  /**
126
132
  * This method is responsible for processing a list of changed files
127
133
  * according to the event source's purpose. As an abstract method, it must
@@ -201,7 +207,12 @@ export default {
201
207
 
202
208
  const driveId = this.getDriveId();
203
209
  const changedFilesStream =
204
- this.googleDrive.listChanges(pageToken, driveId, this.changesPageSize);
210
+ this.googleDrive.listChanges(
211
+ pageToken,
212
+ driveId,
213
+ this.changesPageSize,
214
+ this.getChangesFileFields(),
215
+ );
205
216
  for await (const changedFilesPage of changedFilesStream) {
206
217
  const {
207
218
  changedFiles,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "google_drive-new-access-proposal",
7
7
  name: "New Access Proposal",
8
8
  description: "Emit new event when a new access proposal is requested in Google Drive",
9
- version: "0.0.18",
9
+ version: "0.0.20",
10
10
  type: "source",
11
11
  dedupe: "unique",
12
12
  props: {
@@ -11,7 +11,7 @@ export default {
11
11
  key: "google_drive-new-files-instant",
12
12
  name: "New Files (Instant)",
13
13
  description: "Emit new event when a new file is added in your linked Google Drive",
14
- version: "0.2.15",
14
+ version: "0.2.17",
15
15
  type: "source",
16
16
  dedupe: "unique",
17
17
  props: {
@@ -8,7 +8,7 @@ export default {
8
8
  key: "google_drive-new-files-instant-polling",
9
9
  name: "New Files (Polling)",
10
10
  description: "Emit new event when a new file is added in your linked Google Drive",
11
- version: "0.0.13",
11
+ version: "0.0.15",
12
12
  type: "source",
13
13
  dedupe: "unique",
14
14
  props: {
@@ -7,7 +7,7 @@ export default {
7
7
  key: "google_drive-new-files-shared-drive",
8
8
  name: "New Files (Shared Drive)",
9
9
  description: "Emit new event when a new file is added in your shared Google Drive",
10
- version: "0.1.15",
10
+ version: "0.1.17",
11
11
  type: "source",
12
12
  dedupe: "unique",
13
13
  props: {
@@ -18,7 +18,7 @@ export default {
18
18
  name: "New or Modified Comments (Instant)",
19
19
  description:
20
20
  "Emit new event when a comment is created or modified in the selected file",
21
- version: "1.0.24",
21
+ version: "1.0.26",
22
22
  type: "source",
23
23
  // Dedupe events based on the "x-goog-message-number" header for the target channel:
24
24
  // https://developers.google.com/drive/api/v3/push#making-watch-requests
@@ -7,7 +7,7 @@ export default {
7
7
  key: "google_drive-new-or-modified-comments-polling",
8
8
  name: "New or Modified Comments (Polling)",
9
9
  description: "Emit new event when a comment is created or modified in the selected file",
10
- version: "0.0.13",
10
+ version: "0.0.15",
11
11
  type: "source",
12
12
  dedupe: "unique",
13
13
  props: {
@@ -9,15 +9,17 @@
9
9
  // 2) A timer that runs on regular intervals, renewing the notification channel as needed
10
10
 
11
11
  import {
12
+ CHANGED_FILE_FIELDS,
13
+ GOOGLE_DRIVE_MIME_TYPE_PREFIX,
12
14
  GOOGLE_DRIVE_NOTIFICATION_ADD,
13
15
  GOOGLE_DRIVE_NOTIFICATION_CHANGE,
14
16
  GOOGLE_DRIVE_NOTIFICATION_UPDATE,
17
+ PDF_EXPORTABLE_MIME_TYPES,
15
18
  } from "../../common/constants.mjs";
16
19
  import commonDedupeChanges from "../common-dedupe-changes.mjs";
17
20
  import common from "../common-webhook.mjs";
18
21
  import { stashFile } from "../../common/utils.mjs";
19
22
  import sampleEmit from "./test-event.mjs";
20
- import md5 from "md5";
21
23
 
22
24
  const { googleDrive } = common.props;
23
25
 
@@ -26,10 +28,8 @@ export default {
26
28
  key: "google_drive-new-or-modified-files",
27
29
  name: "New or Modified Files (Instant)",
28
30
  description: "Emit new event when a file in the selected Drive is created, modified or trashed.",
29
- version: "0.4.15",
31
+ version: "1.0.1",
30
32
  type: "source",
31
- // Dedupe events based on the "x-goog-message-number" header for the target channel:
32
- // https://developers.google.com/drive/api/v3/push#making-watch-requests
33
33
  dedupe: "unique",
34
34
  props: {
35
35
  ...common.props,
@@ -66,7 +66,7 @@ export default {
66
66
  includeLink: {
67
67
  label: "Include Link",
68
68
  type: "boolean",
69
- description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.",
69
+ description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. Files that can't be downloaded emit `fileURLError` instead. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.",
70
70
  default: false,
71
71
  optional: true,
72
72
  },
@@ -113,31 +113,25 @@ export default {
113
113
  GOOGLE_DRIVE_NOTIFICATION_UPDATE,
114
114
  ];
115
115
  },
116
- generateMeta(data, headers) {
117
- const {
118
- id: fileId,
119
- name: summary,
120
- modifiedTime: tsString,
121
- } = data;
122
- const ts = Date.parse(tsString);
123
- const eventId = headers && headers["x-goog-message-number"];
124
-
116
+ getChangesFileFields() {
117
+ return CHANGED_FILE_FIELDS;
118
+ },
119
+ generateMeta({
120
+ id, name, modifiedTime, trashed,
121
+ }) {
125
122
  return {
126
- id: md5(`${fileId}-${eventId || ts}`),
127
- summary,
128
- ts,
123
+ id: `${id}-${modifiedTime}-${trashed}`,
124
+ summary: name,
125
+ ts: Date.parse(modifiedTime),
129
126
  };
130
127
  },
131
- async getChanges(headers) {
128
+ getChanges(headers) {
132
129
  if (!headers) {
133
130
  return {
134
- change: { },
131
+ change: {},
135
132
  };
136
133
  }
137
- const resourceUri = headers["x-goog-resource-uri"];
138
- const metadata = await this.googleDrive.getFileMetadata(`${resourceUri}&fields=*`);
139
134
  return {
140
- ...metadata,
141
135
  change: {
142
136
  state: headers["x-goog-resource-state"],
143
137
  resourceURI: headers["x-goog-resource-uri"],
@@ -145,30 +139,53 @@ export default {
145
139
  },
146
140
  };
147
141
  },
142
+ async getFileLink(file) {
143
+ const { mimeType } = file;
144
+ if (mimeType.startsWith(GOOGLE_DRIVE_MIME_TYPE_PREFIX)
145
+ && !PDF_EXPORTABLE_MIME_TYPES.includes(mimeType)) {
146
+ return {
147
+ fileURLError: `Files of type ${mimeType} can't be downloaded`,
148
+ };
149
+ }
150
+ try {
151
+ return {
152
+ fileURL: await stashFile(file, this.googleDrive, this.dir),
153
+ };
154
+ } catch (error) {
155
+ // Isolate per-file failures so one file can't block the page token; rate limits still retry
156
+ if (this.googleDrive.isRetryableError(error, error.status || error.response?.status)) {
157
+ throw error;
158
+ }
159
+ console.log(`Could not upload file ${file.name} to the File Stash: ${error.message}`);
160
+ return {
161
+ fileURLError: error.message,
162
+ };
163
+ }
164
+ },
148
165
  async processChanges(changedFiles, headers) {
149
- const changes = await this.getChanges(headers);
150
-
151
- const filteredFiles = this.checkMinimumInterval(changedFiles);
166
+ const changes = this.getChanges(headers);
167
+ const filteredFiles = this.filterByMinimumInterval(changedFiles);
168
+ const emittedFileIds = [];
152
169
 
153
- for (const file of filteredFiles) {
154
- file.parents = (await this.googleDrive.getFile(file.id, {
155
- fields: "parents",
156
- })).parents;
170
+ try {
171
+ for (const file of filteredFiles) {
172
+ if (!this.shouldProcess(file)) {
173
+ console.log(`Skipping file ${file.name}`);
174
+ continue;
175
+ }
157
176
 
158
- if (!this.shouldProcess(file)) {
159
- console.log(`Skipping file ${file.name}`);
160
- continue;
161
- }
162
-
163
- const eventToEmit = {
164
- file,
165
- ...changes,
166
- };
167
- if (this.includeLink) {
168
- eventToEmit.fileURL = await stashFile(file, this.googleDrive, this.dir);
177
+ const eventToEmit = {
178
+ file,
179
+ ...changes,
180
+ };
181
+ if (this.includeLink) {
182
+ Object.assign(eventToEmit, await this.getFileLink(file));
183
+ }
184
+ this.$emit(eventToEmit, this.generateMeta(file));
185
+ emittedFileIds.push(file.id);
169
186
  }
170
- const meta = this.generateMeta(file, headers);
171
- this.$emit(eventToEmit, meta);
187
+ } finally {
188
+ this.recordFileEmits(emittedFileIds);
172
189
  }
173
190
  },
174
191
  },
@@ -1 +1,30 @@
1
- export default JSON.parse("{\n \"file\": {\n \"kind\": \"drive#file\",\n \"copyRequiresWriterPermission\": false,\n \"writersCanShare\": true,\n \"viewedByMe\": true,\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\",\n \"exportLinks\": {\n \"application/x-vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&exportFormat=ods\",\n \"text/tab-separated-values\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXnViTOo&exportFormat=tsv\",\n \"application/pdf\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaBViTOo&exportFormat=pdf\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbOo&exportFormat=xlsx\",\n \"text/csv\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbBViTOo&exportFormat=csv\",\n \"application/zip\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-VbTmw4Pt2BViTOo&exportFormat=zip\",\n \"application/vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbViTOo&exportFormat=ods\"\n },\n \"parents\": [\n \"0ANs73yKKVA\"\n ],\n \"thumbnailLink\": \"https://docs.google.com/feeds/vt?gd=true&id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&v=12&s=AMedNnoAAAAAZKWjrEqscucFpYCyRCJqnd0wtBiDtXYh&sz=s220\",\n \"iconLink\": \"https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.spreadsheet\",\n \"shared\": false,\n \"lastModifyingUser\": {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"077423361841532483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n },\n \"owners\": [\n {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"07742336189483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n }\n ],\n \"webViewLink\": \"https://docs.google.com/spreadsheets/d/1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmwTOo/edit?usp=drivesdk\",\n \"size\": \"1024\",\n \"viewersCanCopyContent\": true,\n \"permissions\": [\n {\n \"id\": \"07742336184153259483\",\n \"displayName\": \"John Doe\",\n \"type\": \"user\",\n \"kind\": \"drive#permission\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\",\n \"emailAddress\": \"john@doe.com\",\n \"role\": \"owner\",\n \"deleted\": false,\n \"pendingOwner\": false\n }\n ],\n \"hasThumbnail\": true,\n \"spaces\": [\n \"drive\"\n ],\n \"id\": \"1LmXTIQ0wqKP7T3-l9r127Maw4Pt2BViTOo\",\n \"name\": \"Pipedream 2213\",\n \"starred\": false,\n \"trashed\": false,\n \"explicitlyTrashed\": false,\n \"createdTime\": \"2023-02-06T15:13:33.023Z\",\n \"modifiedTime\": \"2023-06-28T12:52:54.570Z\",\n \"modifiedByMeTime\": \"2023-06-28T12:52:54.570Z\",\n \"viewedByMeTime\": \"2023-06-29T06:30:58.441Z\",\n \"quotaBytesUsed\": \"1024\",\n \"version\": \"53\",\n \"ownedByMe\": true,\n \"isAppAuthorized\": false,\n \"capabilities\": {\n \"canChangeViewersCanCopyContent\": true,\n \"canEdit\": true,\n \"canCopy\": true,\n \"canComment\": true,\n \"canAddChildren\": false,\n \"canDelete\": true,\n \"canDownload\": true,\n \"canListChildren\": false,\n \"canRemoveChildren\": false,\n \"canRename\": true,\n \"canTrash\": true,\n \"canReadRevisions\": true,\n \"canChangeCopyRequiresWriterPermission\": true,\n \"canMoveItemIntoTeamDrive\": true,\n \"canUntrash\": true,\n \"canModifyContent\": true,\n \"canMoveItemOutOfDrive\": true,\n \"canAddMyDriveParent\": false,\n \"canRemoveMyDriveParent\": true,\n \"canMoveItemWithinDrive\": true,\n \"canShare\": true,\n \"canMoveChildrenWithinDrive\": false,\n \"canModifyContentRestriction\": true,\n \"canChangeSecurityUpdateEnabled\": false,\n \"canAcceptOwnership\": false,\n \"canReadLabels\": true,\n \"canModifyLabels\": true\n },\n \"thumbnailVersion\": \"12\",\n \"modifiedByMe\": true,\n \"permissionIds\": [\n \"07742336184153259483\"\n ],\n \"linkShareMetadata\": {\n \"securityUpdateEligible\": false,\n \"securityUpdateEnabled\": true\n }\n }\n}");
1
+ export default {
2
+ "file": {
3
+ "kind": "drive#file",
4
+ "id": "1eWLQU_76tvfXptBGkdnjmPbpwhrOtkYS",
5
+ "name": "Quarterly Report.csv",
6
+ "mimeType": "text/csv",
7
+ "parents": [
8
+ "1jPHKePO9_B4jDvpBFyAs38Ji_tCDdjxI",
9
+ ],
10
+ "createdTime": "2026-09-28T17:51:38.475Z",
11
+ "modifiedTime": "2026-09-28T18:04:12.918Z",
12
+ "trashed": false,
13
+ "version": "4",
14
+ "size": "2048",
15
+ "md5Checksum": "5d41402abc4b2a76b9719d911017c592",
16
+ "webViewLink": "https://drive.google.com/file/d/1eWLQU_76tvfXptBGkdnjmPbpwhrOtkYS/view?usp=drivesdk",
17
+ "lastModifyingUser": {
18
+ "kind": "drive#user",
19
+ "displayName": "John Doe",
20
+ "me": true,
21
+ "permissionId": "07742336189483",
22
+ "emailAddress": "john@doe.com",
23
+ "photoLink": "https://lh3.googleusercontent.com/a/default-user=s64",
24
+ },
25
+ },
26
+ "change": {
27
+ "state": "change",
28
+ "resourceURI": "https://www.googleapis.com/drive/v3/changes?alt=json&pageToken=1794",
29
+ },
30
+ };
@@ -9,7 +9,7 @@ export default {
9
9
  key: "google_drive-new-or-modified-files-polling",
10
10
  name: "New or Modified Files (Polling)",
11
11
  description: "Emit new event when a file in the selected Drive is created, modified or trashed. [See the documentation](https://developers.google.com/drive/api/v3/reference/changes/list)",
12
- version: "0.0.15",
12
+ version: "0.0.17",
13
13
  type: "source",
14
14
  dedupe: "unique",
15
15
  props: {
@@ -21,7 +21,7 @@ export default {
21
21
  key: "google_drive-new-or-modified-folders",
22
22
  name: "New or Modified Folders (Instant)",
23
23
  description: "Emit new event when a folder is created or modified in the selected Drive",
24
- version: "0.2.18",
24
+ version: "0.2.20",
25
25
  type: "source",
26
26
  // Dedupe events based on the "x-goog-message-number" header for the target channel:
27
27
  // https://developers.google.com/drive/api/v3/push#making-watch-requests
@@ -12,7 +12,7 @@ export default {
12
12
  key: "google_drive-new-or-modified-folders-polling",
13
13
  name: "New or Modified Folders (Polling)",
14
14
  description: "Emit new event when a folder is created or modified in the selected Drive",
15
- version: "0.0.14",
15
+ version: "0.0.16",
16
16
  type: "source",
17
17
  dedupe: "unique",
18
18
  props: {
@@ -5,7 +5,7 @@ export default {
5
5
  key: "google_drive-new-shared-drive",
6
6
  name: "New Shared Drive",
7
7
  description: "Emits a new event any time a shared drive is created.",
8
- version: "0.1.25",
8
+ version: "0.1.27",
9
9
  type: "source",
10
10
  dedupe: "unique",
11
11
  props: {
@@ -6,7 +6,7 @@ export default {
6
6
  type: "source",
7
7
  name: "New Spreadsheet (Instant)",
8
8
  description: "Emit new event when a new spreadsheet is created in a drive.",
9
- version: "0.1.28",
9
+ version: "0.1.30",
10
10
  props: {
11
11
  googleDrive: newFilesInstant.props.googleDrive,
12
12
  db: newFilesInstant.props.db,
@@ -8,7 +8,7 @@ export default {
8
8
  key: "google_drive-new-spreadsheet-polling",
9
9
  name: "New Spreadsheet (Polling)",
10
10
  description: "Emit new event when a new spreadsheet is created in a drive.",
11
- version: "0.0.13",
11
+ version: "0.0.15",
12
12
  type: "source",
13
13
  dedupe: "unique",
14
14
  props: {