-
Notifications
You must be signed in to change notification settings - Fork 5.5k
18073 trigger new or modified folders instant subfolder support #18091
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
18073 trigger new or modified folders instant subfolder support #18091
Conversation
- Bumped versions for multiple actions and sources to ensure compatibility and reflect recent changes. - Enhanced the 'New or Modified Folders' source to include options for parent folder selection and subfolder inclusion. - Improved event handling and filtering for various actions related to file and folder management.
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
WalkthroughPatch releases across Google Drive actions and sources with mostly version bumps and import reorders. One functional action change improves file upload handling. The “New or Modified Folders” source adds filtering by parent folder and optional subfolder inclusion, adjusts processing limits, and modifies event emission to use changed file objects. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Source as New/Modified Folders Source
participant DriveAPI as Google Drive API
participant Emitter
User->>Source: Configure folderId, includeSubfolders
Source->>DriveAPI: List recent changes
DriveAPI-->>Source: Changed files/folders
alt includeSubfolders = true
Source->>DriveAPI: Traverse parents (getAllParents)
end
Source->>Source: Filter changes by folderId/root and type=folder
Source->>Source: Truncate to maxResults
Source->>Emitter: Emit event (file, meta from changed file)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (4)
components/google_drive/actions/search-shared-drives/search-shared-drives.mjs (1)
15-16
: Fix typo in user-facing description (“shard” → “shared”)This appears in the action description and surfaced to users. Please correct.
Apply this diff:
- "The [shared drives](https://support.google.com/a/users/answer/9310351) search query. See [query terms](https://developers.google.com/drive/api/v3/ref-search-terms#drive_properties) for a list of shard drive-specific query terms.", + "The [shared drives](https://support.google.com/a/users/answer/9310351) search query. See [query terms](https://developers.google.com/drive/api/v3/ref-search-terms#drive_properties) for a list of shared drive-specific query terms.",components/google_drive/actions/list-files/list-files.mjs (1)
86-88
: Preserve pagination by always includingnextPageToken
infields
.If the user provides custom
fields
withoutnextPageToken
, subsequent pages won't be fetched, silently truncating results. EnsurenextPageToken
is present.Apply this diff:
- if (this.fields) { - opts.fields = this.fields; - } + if (this.fields) { + const baseFields = this.fields.trim(); + opts.fields = /\bnextPageToken\b/.test(baseFields) + ? baseFields + : `nextPageToken, ${baseFields}`; + }components/google_drive/actions/upload-file/upload-file.mjs (2)
91-97
: Allow reassignment of mimeType for inferred defaultsTo support inferring mimeType from the source (see next comment), we need mimeType to be mutable.
- const { - parentId, - filePath, - name, - mimeType, - } = this; + let { + parentId, + filePath, + name, + mimeType, + } = this;
110-112
: Avoid introducing a breaking change on MIME type handlingThrowing when metadata.mimeType is set but the mimeType prop is not provided breaks existing workflows that relied on setting conversion via metadata only. Previous behavior allowed conversion using metadata.mimeType alone. Prefer inferring the media mimeType from the source when not explicitly provided.
Replace the error with a safe fallback:
- if (metadata?.mimeType && !mimeType) { - throw new ConfigurationError(`Please include the file's original MIME type in the \`Mime Type\` prop. File will be converted to \`${metadata.mimeType}\`.`); - } + if (!mimeType && fileMetadata?.mimeType) { + mimeType = fileMetadata.mimeType; + }This preserves backward compatibility and still lets users control conversion via metadata.mimeType when desired.
🧹 Nitpick comments (16)
components/google_drive/actions/delete-file/delete-file.mjs (1)
38-38
: Close the parenthesis in the summary message.Cosmetic fix to improve UX of the run summary.
Apply this diff:
- $.export("$summary", `Successfully deleted file (ID: ${fileId}`); + $.export("$summary", `Successfully deleted file (ID: ${fileId})`);components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs (1)
35-43
: Normalize the path to avoid empty segments (trailing/duplicate slashes).Trailing or repeated slashes (e.g., "foo/bar/" or "foo//bar") will produce empty parts and cause an unnecessary lookup for a folder with an empty name. Normalize the path by trimming and filtering falsy segments.
Apply this diff:
- const parts = this.path.split("/"); + const parts = this.path + .split("/") + .map((p) => p.trim()) + .filter(Boolean);components/google_drive/actions/list-files/list-files.mjs (1)
74-80
: Escape filter text to prevent malformed Drive queries and avoid accidental injection.Unescaped single quotes or backslashes in
filterText
can break theq
expression and trigger 400s from the Drive API. Escape them before building the query.Apply this diff:
- if (this.filterText) { - opts.q += `${opts.q - ? " AND " - : ""}name ${this.filterType === "CONTAINS" - ? "contains" - : "="} '${this.filterText}'`; - } + if (this.filterText) { + const escaped = String(this.filterText).replace(/(['\\])/g, "\\$1"); + opts.q += `${opts.q + ? " AND " + : ""}name ${this.filterType === "CONTAINS" + ? "contains" + : "="} '${escaped}'`; + }components/google_drive/actions/update-file/update-file.mjs (1)
144-144
: Fix$summary
to display the file name (not ID) when renaming.The message currently outputs the file ID when a
name
is provided, which is confusing. Prefer the file name, optionally including the ID if desired.Apply this diff:
- $.export("$summary", `Successfully updated the file, "${name ? resp.id : resp.name}"`); + $.export("$summary", `Successfully updated the file, "${resp.name}"`);Optional alternative (if you want both):
- $.export("$summary", `Successfully updated the file, "${name ? resp.id : resp.name}"`); + $.export("$summary", `Successfully updated the file, "${resp.name}" (ID: ${resp.id})`);components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs (1)
12-16
: Nit: Alert copy references the wrong action name.The link points to delete-file but the text says “Move File to Trash”. Suggest aligning the text to “Delete File”.
Apply this diff:
- content: "If you want to **permanently** delete a file instead, use the **[Move File to Trash](https://pipedream.com/apps/google-drive/actions/delete-file)** action.", + content: "If you want to **permanently** delete a file instead, use the **[Delete File](https://pipedream.com/apps/google-drive/actions/delete-file)** action.",components/google_drive/actions/create-folder/create-folder.mjs (1)
72-81
: Escape folder names in Drive query to avoid malformed queries.Building the query with an unescaped
name
can break when it contains'
or\
and may cause false negatives.Apply this diff to escape the name before interpolation:
if (createIfUnique) { - let q = `mimeType = '${GOOGLE_DRIVE_FOLDER_MIME_TYPE}' and name = '${name}' and trashed = false`; + const escapedName = String(name ?? "") + .replaceAll("\\", "\\\\") + .replaceAll("'", "\\'"); + let q = `mimeType = '${GOOGLE_DRIVE_FOLDER_MIME_TYPE}' and name = '${escapedName}' and trashed = false`; if (parentId) { q += ` and '${parentId}' in parents`; } else if (drive === MY_DRIVE_VALUE) { q += " and 'root' in parents"; } else { q += ` and '${driveId}' in parents`; }If preferred, I can extract an
escapeDriveQueryValue
helper in common utils and replace usages across actions.components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs (2)
139-147
: Skip per-file parents fetch when no folder filter is set.Minor optimization: you always fetch parents even when folders filter is empty (watchedFolders.size == 0 path), which isn’t needed.
For example:
// Before file.parents = (await this.googleDrive.getFile(file.id, { fields: "parents" })).parents; // After (only when filtering by folders) if (this.folders?.length) { const { parents = [] } = await this.googleDrive.getFile(file.id, { fields: "parents" }); file.parents = parents; }
144-148
: Remove debug logs or gate them behind a verbosity flag.Unnecessary console logs can spam user logs for high-volume changes.
- console.log(file); // see what file was processed ... - console.log(`Skipping file ${file.name}`);components/google_drive/actions/find-folder/find-folder.mjs (1)
52-55
: Throw an Error, not a string.Re-throwing a string loses stack and type. Wrap the API error in an Error to preserve stack trace and structured handling.
- } catch (error) { - console.log("Failed to find folders with query", error.response?.data?.error || error); - throw JSON.stringify(error.response?.data?.error, null, 2); - } + } catch (error) { + const details = error?.response?.data?.error || error; + console.log("Failed to find folders with query", details); + const message = typeof details === "string" ? details : JSON.stringify(details, null, 2); + throw new Error(message); + }components/google_drive/actions/move-file/move-file.mjs (2)
28-38
: Target folder should be required.Moving a file without a destination folder likely errors or orphans the file. Consider making folderId required.
folderId: { propDefinition: [ googleDrive, "folderId", (c) => ({ drive: c.drive, }), ], description: "The folder you want to move the file to", - optional: true, + optional: false, },
44-48
: Guard against missing parents when removing.If file.parents is undefined/empty, join(",") can throw or send an empty string. Guard accordingly.
- const resp = await this.googleDrive.updateFile(this.fileId, { - fields: "*", - removeParents: file.parents.join(","), - addParents: this.folderId, - }); + const removeParents = Array.isArray(file.parents) && file.parents.length + ? file.parents.join(",") + : undefined; + const resp = await this.googleDrive.updateFile(this.fileId, { + fields: "*", + removeParents, + addParents: this.folderId, + });components/google_drive/actions/upload-file/upload-file.mjs (2)
100-105
: Ensure a safe filename fallbackfilename may be undefined if the source doesn’t provide a name (some URLs/streams). Consider a robust fallback to avoid API errors.
Apply this minimal diff to add a fallback:
- const filename = name || fileMetadata.name; + const filename = name || fileMetadata?.name || `uploaded-file-${Date.now()}`;If you’d prefer deriving the name from the provided path/URL, add this import and logic outside the selected range:
// at top-level imports import { basename } from "node:path";// replace the filename line with: const filename = name || fileMetadata?.name || (filePath?.includes("://") ? new URL(filePath).pathname.split("/").pop() : basename(filePath || "")) || `uploaded-file-${Date.now()}`;
120-125
: Nit: remove uploadType from metadata-only updateuploadType is only relevant to media uploads. This call updates metadata after media is updated separately, so uploadType can be omitted to avoid confusion.
- result = await this.googleDrive.updateFile(this.fileId, omitEmptyStringValues({ - name: filename, - mimeType, - uploadType, - requestBody: metadata, - })); + result = await this.googleDrive.updateFile(this.fileId, omitEmptyStringValues({ + name: filename, + mimeType, + requestBody: metadata, + }));components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs (3)
28-48
: Clarify “Parent Folder” semantics and set a safe default for recursionTwo points:
- The current default of
includeSubfolders
is false. When nofolderId
is provided, this effectively limits events to top-level folders only, which likely deviates from the historical behavior (“watch the entire drive”). Consider defaulting to true to preserve prior breadth.- Tighten descriptions so users understand how “Parent Folder” and “Include Subfolders” interact.
Also,
propDefinition
closure relies onc.drive
. Please confirmdrive
is defined oncommon.props
and its value shape is compatible (string literal “My Drive” vs. drive ID).Apply this diff to improve defaults and clarity:
label: "Parent Folder", - description: "The ID of the parent folder which contains the folders. If not specified, it will watch all folders from the drive's top-level folder.", + description: "The ID of the parent folder to scope this source. If not specified, the source watches the entire Drive. Combine with “Include Subfolders” to control recursion.", optional: true, }, includeSubfolders: { type: "boolean", label: "Include Subfolders", - description: "Whether to include subfolders of the parent folder in the changes.", - optional: true, + description: "When enabled, emits events for subfolders nested within the Parent Folder. If no Parent Folder is set, applies to the entire Drive.", + optional: true, + default: true, },To verify
drive
is present and its value type, please run the script in the separate verification comment below.
81-98
: Memoize or bound parent traversal to reduce API calls
getAllParents
walks the chain with one API call per level. For deeply nested structures and bursts of changes, this can be chatty. Consider:
- Caching ancestor results per folder ID within a single
processChanges
invocation.- Adding a sanity bound (e.g., max depth 50) to prevent pathological loops.
I can provide a lightweight memoization pattern scoped to
processChanges
if you want it baked in now.
157-160
: Avoid post-loop array truncation; you’re already short-circuitingGiven the early
break
whenmaxResults
is reached, post-loop truncation becomes redundant. If you’d rather keep the truncation pattern, remove the earlybreak
in favor of the existing slice/truncate; don’t do both.Apply this diff if you keep the early break:
- if (maxResults && filteredFiles.length >= maxResults) { - filteredFiles.length = maxResults; - }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (36)
components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs
(1 hunks)components/google_drive/actions/copy-file/copy-file.mjs
(1 hunks)components/google_drive/actions/create-file-from-template/create-file-from-template.mjs
(1 hunks)components/google_drive/actions/create-file-from-text/create-file-from-text.mjs
(1 hunks)components/google_drive/actions/create-folder/create-folder.mjs
(1 hunks)components/google_drive/actions/create-shared-drive/create-shared-drive.mjs
(1 hunks)components/google_drive/actions/delete-file/delete-file.mjs
(1 hunks)components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs
(1 hunks)components/google_drive/actions/download-file/download-file.mjs
(2 hunks)components/google_drive/actions/find-file/find-file.mjs
(1 hunks)components/google_drive/actions/find-folder/find-folder.mjs
(1 hunks)components/google_drive/actions/find-forms/find-forms.mjs
(1 hunks)components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs
(1 hunks)components/google_drive/actions/get-file-by-id/get-file-by-id.mjs
(1 hunks)components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs
(1 hunks)components/google_drive/actions/get-shared-drive/get-shared-drive.mjs
(1 hunks)components/google_drive/actions/list-access-proposals/list-access-proposals.mjs
(1 hunks)components/google_drive/actions/list-files/list-files.mjs
(1 hunks)components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs
(1 hunks)components/google_drive/actions/move-file/move-file.mjs
(1 hunks)components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs
(1 hunks)components/google_drive/actions/search-shared-drives/search-shared-drives.mjs
(1 hunks)components/google_drive/actions/update-file/update-file.mjs
(1 hunks)components/google_drive/actions/update-shared-drive/update-shared-drive.mjs
(1 hunks)components/google_drive/actions/upload-file/upload-file.mjs
(1 hunks)components/google_drive/package.json
(1 hunks)components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs
(2 hunks)components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs
(2 hunks)components/google_drive/sources/new-access-proposal/new-access-proposal.mjs
(1 hunks)components/google_drive/sources/new-files-instant/new-files-instant.mjs
(1 hunks)components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs
(1 hunks)components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs
(1 hunks)components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs
(2 hunks)components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs
(4 hunks)components/google_drive/sources/new-shared-drive/new-shared-drive.mjs
(1 hunks)components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs (2)
components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs (5)
common
(20-20)filteredFiles
(137-137)changes
(135-135)eventToEmit
(151-154)meta
(155-155)components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs (3)
changes
(106-106)eventToEmit
(125-128)meta
(129-129)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: pnpm publish
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
🔇 Additional comments (54)
components/google_drive/package.json (2)
3-3
: Version bump looks good.Metadata-only update; no dependency changes. Safe to publish.
3-3
: New or Modified Folders (Instant): Props and Logic Verified
All required changes are present incomponents/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs
:
- Version bumped to 0.2.0 (line 23)
- Parent folder selector (
folderId
) and Include Subfolders option defined (lines 30–47)processChanges
filters results by the selected parent (lines 144–152)- Descriptions for Parent Folder and Include Subfolders updated to reflect behavior (lines 37–46)
Please confirm that the call to
this.getListFilesOpts(...)
inrun
correctly includes thedrive
andincludeItemsFromAllDrives
(or equivalent) flags so shared-drive items are scoped properly.components/google_drive/actions/create-file-from-template/create-file-from-template.mjs (1)
11-11
: Patch version bump approved.No functional changes; safe to release.
components/google_drive/actions/get-file-by-id/get-file-by-id.mjs (1)
8-8
: Patch version bump approved.Runtime behavior unchanged.
components/google_drive/actions/delete-file/delete-file.mjs (1)
8-8
: Patch version bump approved.No logic changes; OK to publish.
components/google_drive/actions/get-shared-drive/get-shared-drive.mjs (1)
7-7
: Patch version bump approved.No behavior changes detected.
components/google_drive/actions/list-access-proposals/list-access-proposals.mjs (1)
7-7
: Version bump looks goodPatch version increment only; no behavioral changes in this file. Safe to ship.
components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs (1)
7-7
: Patch version update acknowledgedNo logic changes; version bump aligns with PR’s patch-level updates across actions.
components/google_drive/actions/search-shared-drives/search-shared-drives.mjs (1)
7-7
: Patch version bump approvedNo runtime or API changes in this action; version metadata updated only.
components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs (1)
23-23
: Version bump only; no functional changesLooks consistent with the rest of the PR’s patch updates.
components/google_drive/actions/copy-file/copy-file.mjs (1)
7-7
: Version increment acknowledgedMetadata-only change; behavior unchanged.
components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs (1)
15-15
: Patch version bump only — LGTMNo functional changes; version bump is consistent with the broader patch release.
components/google_drive/actions/list-files/list-files.mjs (1)
2-2
: Import reorder and patch version bump — LGTMNo runtime impact from import order; version bump aligns with related actions in this PR.
Also applies to: 8-8
components/google_drive/actions/create-file-from-text/create-file-from-text.mjs (1)
8-8
: Patch version bump only — LGTMNo functional changes in this action. Implementation remains consistent.
components/google_drive/actions/update-file/update-file.mjs (1)
2-3
: Import ordering and patch version bump — LGTMReordered imports are fine; version bump aligns with other actions.
Also applies to: 9-9
components/google_drive/actions/update-shared-drive/update-shared-drive.mjs (1)
7-7
: Patch version bump only — LGTMNo functional changes; consistent with the broader patch release.
components/google_drive/actions/create-shared-drive/create-shared-drive.mjs (1)
7-7
: Version bump only — LGTMNo functional changes. Patch version increment is appropriate.
components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs (2)
12-12
: Import reorder — LGTMReordering imports has no runtime effect here and aligns with common style.
20-20
: Patch version bump — LGTMNo behavioral changes in this source; version bump is appropriate.
components/google_drive/sources/new-access-proposal/new-access-proposal.mjs (2)
2-2
: Import order change — LGTMMoving the app import under the platform constant is harmless and consistent with the PR’s import tidy-ups.
9-9
: Patch version bump — LGTMNo functional changes; version bump looks good.
components/google_drive/actions/download-file/download-file.mjs (2)
6-7
: Import ordering — LGTMReordered imports are fine and do not affect behavior.
21-21
: Patch version bump — LGTMNo runtime changes; version increment is appropriate.
components/google_drive/actions/find-forms/find-forms.mjs (2)
2-3
: Import order adjustment — LGTMBringing
getListFilesOpts
up is fine and keeps usage close to its import.
9-9
: Subfolder filtering innew-or-modified-folders.mjs
verifiedThe PR’s main enhancement—support for subfolder filtering—has landed as intended:
- New props present:
folderId
(ln 30)includeSubfolders
(ln 42)maxResults
(ln 127)- Helper methods implemented:
getAllParents
(ln 81)processChanges
(ln 127)- Filtering logic correctly checks parents:
- Uses
getAllParents
whenincludeSubfolders
is true (ln 144–152)- Source version updated to “0.2.0” (ln 23)
Patch version bump is fine.
components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs (1)
2-2
: Patch-only changes look good (import order + version bump).No runtime behavior change introduced. Safe to merge.
Also applies to: 8-8
components/google_drive/sources/new-shared-drive/new-shared-drive.mjs (1)
2-2
: LGTM on import reorder and version bump.No functional changes; deploy/run logic remains intact.
Also applies to: 8-8
components/google_drive/actions/create-folder/create-folder.mjs (1)
5-5
: Minor metadata tweaks approved.Import reordering and version bump are fine.
Also applies to: 9-10, 16-16
components/google_drive/actions/find-file/find-file.mjs (1)
2-3
: Approved: import order adjustment and patch version bump.No runtime semantics changed.
Also applies to: 9-9
components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs (1)
9-9
: Version bump approved.No logic changes; behavior unchanged.
components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs (3)
17-18
: Re-introduced imports look correct and necessary.Bringing back common and sampleEmit resolves downstream references (e.g., common.props and sampleEmit export). No behavioral concerns.
27-27
: Version bump to 0.3.8 is fine.Patch-level increment aligns with non-functional import adjustments. No further action needed.
22-28
: New or Modified Folders (Instant) already includes correct folder filtering and descendant support.
- The
folderId
prop is defined for parent‐folder filtering.- The optional
includeSubfolders
boolean is present.- In
processChanges
, whenincludeSubfolders
is true, it callsgetAllParents(file.id)
to collect the entire ancestor chain and matches againstfolderId
(orroot.id
), ensuring true descendant filtering rather than just direct parents.No further action needed here.
components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs (2)
15-17
: Import reordering is a no-op at runtime.No behavior change. Safe patch.
30-30
: Version bump to 0.2.8 is appropriate.Consistent with sibling source bump.
components/google_drive/actions/find-folder/find-folder.mjs (2)
10-10
: Version bump to 0.1.11 is fine.Patch-level change aligns with import/source adjustments in this PR.
42-45
: getListFilesOpts import and signature confirmed
ThegetListFilesOpts
function is exported as a named export incomponents/google_drive/common/utils.mjs
and its signature—function getListFilesOpts(drive, baseOpts = {})
—matches how it’s called infind-folder.mjs
. No changes needed.components/google_drive/actions/move-file/move-file.mjs (1)
7-7
: Version bump to 0.1.11 is fine.No functional change in this action.
components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs (2)
6-6
: Import reordering is benign.No runtime impact. Ok to proceed.
19-19
: Version bump to 0.2.8 is appropriate.Consistent with shared-drive variant.
components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs (2)
1-1
: Import placement cleanup looks goodMoving the DEFAULT_POLLING_SOURCE_TIMER_INTERVAL import to the top resolves duplication and aligns with common import-order conventions.
10-10
: Patch version bump acknowledgedVersion updated to 0.0.5 with no behavioral changes in this file. All good.
components/google_drive/sources/new-files-instant/new-files-instant.mjs (2)
5-6
: Import reordering is fineReordering imports for common-webhook and test-event has no runtime effect and improves consistency.
13-13
: Patch version bump acknowledgedVersion updated to 0.1.16; no functional changes here.
components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs (2)
2-3
: Import order tweak is safeSwitching the order of getListFilesOpts and googleDrive imports has no behavioral impact.
9-9
: Patch version bump acknowledgedVersion updated to 0.1.11; the run logic remains unchanged.
components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs (2)
2-2
: Import order cleanup is fineMoving googleDrive import after ConfigurationError is consistent with the rest of the codebase; no runtime change.
8-8
: Patch version bump acknowledgedVersion updated to 0.0.4; no API changes in this action.
components/google_drive/actions/upload-file/upload-file.mjs (2)
1-5
: Good refactor: centralized helpers and constantsUsing getFileStreamAndMetadata and the shared upload type constant simplifies file handling, supports both URLs and local files, and reduces duplication.
16-16
: Patch version bump acknowledgedVersion updated to 2.0.4. See note below regarding a potential breaking change introduced in this file.
components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs (4)
16-16
: LGTM: import path/use of common-webhookImporting
common
from../common-webhook.mjs
aligns with how other Drive sources wire props and hooks. No issues spotted.
23-23
: Confirm version bump vs. behavior changeDefault behavior appears to change when no Parent Folder is set (see filtering logic). If that’s intentional and potentially breaking for existing users, verify that
0.2.0
is the correct semver bump and consider documenting the change in the component’s changelog/description.Would you like me to draft a concise changelog entry?
160-176
: EnsuremodifiedTime
is always present; otherwise events will re-emitYou now rely on
file.modifiedTime
from the fetched file. IfgetFile
doesn’t include it by default,Date.parse(undefined)
yieldsNaN
, and the equality check will never match, causing repeated emissions. The earlier diff forcesmodifiedTime
into the selected fields, which addresses this.
139-151
: Drive root resolution verifiedThe
drive
prop is defined via thegoogleDrive.watchedDrive
dropdown, which returns either the literal"My Drive"
or a shared-drive ID string. In the Drive API, a shared-drive’s ID is the same as its root‐folder ID, and ourgetFile(id)
wrapper automatically setssupportsAllDrives
. Therefore, passing"root"
for My Drive or the shared-drive ID correctly retrieves the root folder—no changes needed here.
async processChanges(changedFiles, headers, maxResults) { | ||
const files = changedFiles.filter( | ||
// API docs that define Google Drive folders: | ||
// https://developers.google.com/drive/api/v3/folder | ||
(file) => file.mimeType === "application/vnd.google-apps.folder", | ||
); | ||
|
||
const filteredFiles = []; | ||
for (const file of files) { | ||
// The changelog is updated each time a folder is opened. Check the | ||
// folder's `modifiedTime` to see if the folder has been modified. | ||
const fileInfo = await this.googleDrive.getFile(file.id); | ||
const root = await this.googleDrive.getFile(this.drive === "My Drive" | ||
? "root" | ||
: this.drive); | ||
|
||
const allParents = []; | ||
if (this.includeSubfolders) { | ||
allParents.push(...(await this.getAllParents(file.id))); | ||
} else { | ||
allParents.push(fileInfo.parents[0]); | ||
} | ||
|
||
if (!allParents.includes(this.folderId || root.id)) { | ||
continue; | ||
} | ||
|
||
filteredFiles.push(fileInfo); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potentially drops all webhook-driven events: relying on changedFiles.mimeType before fetching file metadata
Webhooks often only provide IDs, not mimeType
. Filtering folders prior to fetching metadata can make files
empty, preventing any event emission. Also, root
is fetched inside the loop, causing unnecessary repeated calls, and getFile
doesn’t request explicit fields (risking modifiedTime
being absent).
Refactor to:
- Fetch
fileInfo
first (with explicit fields), then filter bymimeType
. - Resolve the Drive root once, outside the loop.
- Stop early when
maxResults
is reached.
Apply this diff:
- async processChanges(changedFiles, headers, maxResults) {
- const files = changedFiles.filter(
- // API docs that define Google Drive folders:
- // https://developers.google.com/drive/api/v3/folder
- (file) => file.mimeType === "application/vnd.google-apps.folder",
- );
-
- const filteredFiles = [];
- for (const file of files) {
+ async processChanges(changedFiles, headers, maxResults) {
+ // Resolve the Drive root once to avoid redundant requests inside the loop
+ const root = await this.googleDrive.getFile(
+ this.drive === "My Drive" ? "root" : this.drive,
+ { fields: "id" },
+ );
+ const filteredFiles = [];
+ for (const changed of changedFiles) {
// The changelog is updated each time a folder is opened. Check the
// folder's `modifiedTime` to see if the folder has been modified.
- const fileInfo = await this.googleDrive.getFile(file.id);
- const root = await this.googleDrive.getFile(this.drive === "My Drive"
- ? "root"
- : this.drive);
+ const fileInfo = await this.googleDrive.getFile(changed.id, {
+ fields: "id, name, mimeType, modifiedTime, parents",
+ });
+ // Filter to folders only, regardless of the shape of `changedFiles`
+ if (fileInfo.mimeType !== "application/vnd.google-apps.folder") {
+ continue;
+ }
- const allParents = [];
- if (this.includeSubfolders) {
- allParents.push(...(await this.getAllParents(file.id)));
- } else {
- allParents.push(fileInfo.parents[0]);
- }
+ const allParents = [];
+ if (this.includeSubfolders) {
+ allParents.push(...(await this.getAllParents(fileInfo.id)));
+ } else {
+ allParents.push(fileInfo.parents?.[0]);
+ }
- if (!allParents.includes(this.folderId || root.id)) {
- continue;
- }
+ if (!allParents.includes(this.folderId || root.id)) {
+ continue;
+ }
- filteredFiles.push(fileInfo);
- }
+ filteredFiles.push(fileInfo);
+ if (maxResults && filteredFiles.length >= maxResults) {
+ break;
+ }
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async processChanges(changedFiles, headers, maxResults) { | |
const files = changedFiles.filter( | |
// API docs that define Google Drive folders: | |
// https://developers.google.com/drive/api/v3/folder | |
(file) => file.mimeType === "application/vnd.google-apps.folder", | |
); | |
const filteredFiles = []; | |
for (const file of files) { | |
// The changelog is updated each time a folder is opened. Check the | |
// folder's `modifiedTime` to see if the folder has been modified. | |
const fileInfo = await this.googleDrive.getFile(file.id); | |
const root = await this.googleDrive.getFile(this.drive === "My Drive" | |
? "root" | |
: this.drive); | |
const allParents = []; | |
if (this.includeSubfolders) { | |
allParents.push(...(await this.getAllParents(file.id))); | |
} else { | |
allParents.push(fileInfo.parents[0]); | |
} | |
if (!allParents.includes(this.folderId || root.id)) { | |
continue; | |
} | |
filteredFiles.push(fileInfo); | |
} | |
async processChanges(changedFiles, headers, maxResults) { | |
// Resolve the Drive root once to avoid redundant requests inside the loop | |
const root = await this.googleDrive.getFile( | |
this.drive === "My Drive" ? "root" : this.drive, | |
{ fields: "id" }, | |
); | |
const filteredFiles = []; | |
for (const changed of changedFiles) { | |
// The changelog is updated each time a folder is opened. Check the | |
// folder's `modifiedTime` to see if the folder has been modified. | |
const fileInfo = await this.googleDrive.getFile(changed.id, { | |
fields: "id, name, mimeType, modifiedTime, parents", | |
}); | |
// Filter to folders only, regardless of the shape of `changedFiles` | |
if (fileInfo.mimeType !== "application/vnd.google-apps.folder") { | |
continue; | |
} | |
const allParents = []; | |
if (this.includeSubfolders) { | |
allParents.push(...(await this.getAllParents(fileInfo.id))); | |
} else { | |
allParents.push(fileInfo.parents?.[0]); | |
} | |
if (!allParents.includes(this.folderId || root.id)) { | |
continue; | |
} | |
filteredFiles.push(fileInfo); | |
if (maxResults && filteredFiles.length >= maxResults) { | |
break; | |
} | |
} | |
// …rest of method… | |
} |
🤖 Prompt for AI Agents
In
components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs
around lines 127 to 156, the current code filters by file.mimeType before
fetching metadata which can drop webhook-only events, fetches root inside the
loop, and never respects maxResults; change the loop to first call
this.googleDrive.getFile(file.id) requesting explicit fields (id, mimeType,
parents, modifiedTime), then skip non-folder mimeTypes, resolve the Drive root
once before the loop (root = await this.googleDrive.getFile(this.drive === "My
Drive" ? "root" : this.drive)), ensure fileInfo.parents is handled safely
(fallback if missing), push parents via includeSubfolders logic, stop processing
and break the loop when filteredFiles.length reaches maxResults, and push
fileInfo into filteredFiles only after these checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Resolves #18073
Summary by CodeRabbit
New Features
Chores