-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[Components] tmetric #13315 #19287
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
base: master
Are you sure you want to change the base?
[Components] tmetric #13315 #19287
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
WalkthroughThis PR introduces three new time entry management actions (Create, Modify, Delete) for the TMetric integration. The app configuration is enhanced with propDefinitions for time entry fields, HTTP utility methods, and CRUD operations to support these actions. The package version is updated to 0.1.0 with the addition of Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Comment |
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: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
components/tmetric/actions/create-time-entry/create-time-entry.mjs(1 hunks)components/tmetric/actions/delete-time-entry/delete-time-entry.mjs(1 hunks)components/tmetric/actions/modify-time-entry/modify-time-entry.mjs(1 hunks)components/tmetric/package.json(2 hunks)components/tmetric/tmetric.app.mjs(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
Repo: PipedreamHQ/pipedream PR: 14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
Applied to files:
components/tmetric/actions/create-time-entry/create-time-entry.mjs
📚 Learning: 2024-12-12T19:23:09.039Z
Learnt from: jcortes
Repo: PipedreamHQ/pipedream PR: 14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.
Applied to files:
components/tmetric/package.json
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.
Applied to files:
components/tmetric/tmetric.app.mjs
📚 Learning: 2025-09-15T22:01:11.472Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 18362
File: components/leonardo_ai/actions/generate-image/generate-image.mjs:103-105
Timestamp: 2025-09-15T22:01:11.472Z
Learning: In Pipedream components, pipedream/platform's axios implementation automatically excludes undefined values from HTTP requests, so there's no need to manually check for truthiness before including properties in request payloads.
Applied to files:
components/tmetric/tmetric.app.mjs
🧬 Code graph analysis (4)
components/tmetric/actions/modify-time-entry/modify-time-entry.mjs (3)
components/tmetric/actions/create-time-entry/create-time-entry.mjs (1)
response(54-64)components/tmetric/actions/delete-time-entry/delete-time-entry.mjs (1)
response(33-39)components/tmetric/tmetric.app.mjs (2)
response(12-12)response(27-29)
components/tmetric/actions/delete-time-entry/delete-time-entry.mjs (2)
components/tmetric/actions/create-time-entry/create-time-entry.mjs (1)
response(54-64)components/tmetric/actions/modify-time-entry/modify-time-entry.mjs (1)
response(63-74)
components/tmetric/actions/create-time-entry/create-time-entry.mjs (3)
components/tmetric/actions/delete-time-entry/delete-time-entry.mjs (1)
response(33-39)components/tmetric/actions/modify-time-entry/modify-time-entry.mjs (1)
response(63-74)components/tmetric/tmetric.app.mjs (2)
response(12-12)response(27-29)
components/tmetric/tmetric.app.mjs (3)
components/tmetric/actions/create-time-entry/create-time-entry.mjs (1)
response(54-64)components/tmetric/actions/delete-time-entry/delete-time-entry.mjs (1)
response(33-39)components/tmetric/actions/modify-time-entry/modify-time-entry.mjs (1)
response(63-74)
⏰ 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: Verify TypeScript components
- GitHub Check: Publish TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Lint Code Base
🔇 Additional comments (3)
components/tmetric/package.json (1)
3-17: Version bump and dependency addition look appropriateThe version bump and addition of
@pipedream/platformalign with the new HTTP helper usage intmetric.app.mjs, and no built‑in Node modules are added as dependencies, which matches prior guidance. Based on learnings, this setup looks good.components/tmetric/tmetric.app.mjs (1)
70-129: App HTTP helper and time‑entry methods are cohesive and consistent
_baseUrl/_makeRequestcentralize auth and URL construction, and thecreateTimeEntry,deleteTimeEntry,modifyTimeEntry,getTimeEntries, andgetUsermethods all use this helper consistently. TheaccountId/timeEntryIdpropDefinitions correctly rely on these methods for options. No structural issues spotted.components/tmetric/actions/modify-time-entry/modify-time-entry.mjs (1)
68-73: Remove?? ""coercion fromstartTimeandendTimein modify-time-entry actionThe current implementation uses
startTime: this.startTime ?? ""andendTime: this.endTime ?? ""(lines 68–69), which forces empty strings when fields are undefined. For a PUT update operation, this risks unintentionally clearing existing values instead of leaving them unchanged.The prop definitions explicitly mark these fields as optional and describe leaving them null for special API behavior (e.g., "leave null to start the timer at the current moment"). Sending empty strings bypasses this intent and prevents the API from handling omitted fields as expected.
Recommend removing the coercion:
- data: { - startTime: this.startTime ?? "", - endTime: this.endTime ?? "", - note: this.note, - isBillable: this.isBillable, - isInvoiced: this.isInvoiced, - }, + data: { + startTime: this.startTime, + endTime: this.endTime, + note: this.note, + isBillable: this.isBillable, + isInvoiced: this.isInvoiced, + },
| startTime: this.startTime ?? "", | ||
| endTime: this.endTime ?? "", | ||
| note: this.note, | ||
| isBillable: this.isBillable, | ||
| isInvoiced: this.isInvoiced, | ||
| }, |
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.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's find and examine the create-time-entry.mjs file
fd -t f "create-time-entry.mjs" | head -20Repository: PipedreamHQ/pipedream
Length of output: 464
🏁 Script executed:
#!/bin/bash
# Read the tmetric create-time-entry.mjs file
cat -n components/tmetric/actions/create-time-entry/create-time-entry.mjsRepository: PipedreamHQ/pipedream
Length of output: 2263
🏁 Script executed:
#!/bin/bash
# Find and read tmetric app file
fd -t f "tmetric.app.mjs"Repository: PipedreamHQ/pipedream
Length of output: 99
🏁 Script executed:
#!/bin/bash
# Read the tmetric app file to see propDefinitions and createTimeEntry
cat -n components/tmetric/tmetric.app.mjsRepository: PipedreamHQ/pipedream
Length of output: 4184
🏁 Script executed:
#!/bin/bash
# Search for modify-time-entry action in tmetric
fd -t f "modify-time-entry.mjs" components/tmetric/Repository: PipedreamHQ/pipedream
Length of output: 131
🏁 Script executed:
#!/bin/bash
# Read modify-time-entry.mjs to check for same pattern
cat -n components/tmetric/actions/modify-time-entry/modify-time-entry.mjsRepository: PipedreamHQ/pipedream
Length of output: 2555
Avoid coercing missing startTime / endTime to empty strings
Using this.startTime ?? "" and this.endTime ?? "" forces empty strings into the payload when the user leaves these props blank. This conflicts with the API documentation in propDefinitions ("leave null to start the timer at the current moment" and "leave null to keep the timer running indefinitely") and prevents relying on the platform client's behavior of omitting undefined fields.
You can pass the values directly and let undefined be dropped from the request:
- data: {
- startTime: this.startTime ?? "",
- endTime: this.endTime ?? "",
- note: this.note,
- isBillable: this.isBillable,
- isInvoiced: this.isInvoiced,
- },
+ data: {
+ startTime: this.startTime,
+ endTime: this.endTime,
+ note: this.note,
+ isBillable: this.isBillable,
+ isInvoiced: this.isInvoiced,
+ },Apply this same adjustment to the modify-time-entry action (lines 68-69) for consistency.
📝 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.
| startTime: this.startTime ?? "", | |
| endTime: this.endTime ?? "", | |
| note: this.note, | |
| isBillable: this.isBillable, | |
| isInvoiced: this.isInvoiced, | |
| }, | |
| startTime: this.startTime, | |
| endTime: this.endTime, | |
| note: this.note, | |
| isBillable: this.isBillable, | |
| isInvoiced: this.isInvoiced, | |
| }, |
🤖 Prompt for AI Agents
In components/tmetric/actions/create-time-entry/create-time-entry.mjs around
lines 58 to 63, the code coerces missing startTime/endTime to empty strings
using "this.startTime ?? ''" and "this.endTime ?? ''"; change these to pass the
properties directly (this.startTime and this.endTime) so undefined values are
preserved and can be omitted by the platform client; also make the same
adjustment in the modify-time-entry action at lines 68-69 to keep behavior
consistent.
| $.export("$summary", "Successfully created time entry with ID: " + response[0].id); | ||
| return response; |
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.
🧹 Nitpick | 🔵 Trivial
Defensively handle the createTimeEntry response shape when building the summary
The summary assumes createTimeEntry returns an array (response[0].id). If the API instead returns a single object, this will produce undefined in the summary.
You can support both shapes with a small adjustment:
- $.export("$summary", "Successfully created time entry with ID: " + response[0].id);
- return response;
+ const timeEntry = Array.isArray(response) ? response[0] : response;
+ $.export("$summary", `Successfully created time entry with ID: ${timeEntry.id}`);
+ return response;This keeps the summary robust even if the API or client behavior changes.
🤖 Prompt for AI Agents
In components/tmetric/actions/create-time-entry/create-time-entry.mjs around
lines 65-66, the summary currently assumes response is an array and uses
response[0].id which can be undefined if the API returns a single object; update
the code to normalize the response (check Array.isArray(response) and pick
response[0] when array, otherwise use response), defensively read the id with
optional chaining (e.g. entry?.id) and fall back to a sensible placeholder like
'unknown' before building the export summary string so the summary works for
both array and single-object responses.
| async run({ $ }) { | ||
| const response = await this.app.deleteTimeEntry({ | ||
| $, | ||
| data: { | ||
| accountId: this.accountId, | ||
| timeEntryId: this.timeEntryId, | ||
| }, | ||
| }); |
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.
Fix deleteTimeEntry call: IDs are not passed where the app method expects them
deleteTimeEntry in tmetric.app.mjs destructures accountId and timeEntryId from the top‑level argument, but this action passes them inside data, so both IDs are undefined and the URL becomes /accounts/undefined/timeentries/undefined.
You should pass the IDs at the top level (and you don't need them in the body):
- const response = await this.app.deleteTimeEntry({
- $,
- data: {
- accountId: this.accountId,
- timeEntryId: this.timeEntryId,
- },
- });
+ const response = await this.app.deleteTimeEntry({
+ $,
+ accountId: this.accountId,
+ timeEntryId: this.timeEntryId,
+ });🤖 Prompt for AI Agents
In components/tmetric/actions/delete-time-entry/delete-time-entry.mjs around
lines 32 to 39, the call to this.app.deleteTimeEntry incorrectly nests accountId
and timeEntryId inside a data object so the app method receives undefined IDs;
move accountId and timeEntryId to the top-level of the argument object (e.g.
pass { $, accountId: this.accountId, timeEntryId: this.timeEntryId }) and remove
them from the body/data payload since the endpoint derives IDs from the path.
| type: "string", | ||
| label: "Start Time", | ||
| description: "Start timestamp in ISO format, e.g. `2025-11-26T14:16:00`; leave null to start the timer at the current moment", | ||
| optional: true, | ||
| }, | ||
| endTime: { | ||
| type: "string", | ||
| label: "End Time", | ||
| description: "End timestamp in ISO format, e.g. `2025-11-26T15:16:00`; leave null to keep the timer running indefinitely", | ||
| optional: true, |
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.
🧹 Nitpick | 🔵 Trivial
Clarify “leave null” phrasing in startTime / endTime descriptions
The descriptions say “leave null …”, but in the UI users will typically just leave these fields blank. Consider rephrasing to something like “leave blank to …” to better match how props are actually set:
- description: "Start timestamp in ISO format, e.g. `2025-11-26T14:16:00`; leave null to start the timer at the current moment",
+ description: "Start timestamp in ISO format, e.g. `2025-11-26T14:16:00`; leave blank to start the timer at the current moment",
...
- description: "End timestamp in ISO format, e.g. `2025-11-26T15:16:00`; leave null to keep the timer running indefinitely",
+ description: "End timestamp in ISO format, e.g. `2025-11-26T15:16:00`; leave blank to keep the timer running indefinitely",📝 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.
| type: "string", | |
| label: "Start Time", | |
| description: "Start timestamp in ISO format, e.g. `2025-11-26T14:16:00`; leave null to start the timer at the current moment", | |
| optional: true, | |
| }, | |
| endTime: { | |
| type: "string", | |
| label: "End Time", | |
| description: "End timestamp in ISO format, e.g. `2025-11-26T15:16:00`; leave null to keep the timer running indefinitely", | |
| optional: true, | |
| type: "string", | |
| label: "Start Time", | |
| description: "Start timestamp in ISO format, e.g. `2025-11-26T14:16:00`; leave blank to start the timer at the current moment", | |
| optional: true, | |
| }, | |
| endTime: { | |
| type: "string", | |
| label: "End Time", | |
| description: "End timestamp in ISO format, e.g. `2025-11-26T15:16:00`; leave blank to keep the timer running indefinitely", | |
| optional: true, |
🤖 Prompt for AI Agents
In components/tmetric/tmetric.app.mjs around lines 39 to 48, the field
descriptions for startTime and endTime use the phrase "leave null" which is
misleading for users who will typically leave the form fields blank; update both
descriptions to say "leave blank" (or "omit") and keep the examples and behavior
notes intact so the UI text accurately reflects how props are set when users
don't provide a value.
michelle0927
left a comment
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.
Please evaluate the comments left by coderabbit before marking PRs as Ready for PR Review.
Also, this PR is missing the source requested in the issue.
WHY
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.