-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[Components] attio - added new components #16411
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?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 3 Skipped Deployments
|
WalkthroughThis update introduces significant enhancements and refactoring to the Attio integration components. It adds new actions for creating and updating person records, as well as creating tasks. The webhook source system is refactored to use a new subscription-based event declaration, replacing the previous event type and filter methods. A new source is added to emit events for new activities (notes, tasks, comments). The Attio app is refactored for modularity, with expanded property definitions and unified HTTP request handling. Supporting constants are centralized in a new module, and multiple component versions are incremented to reflect these changes. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant AttioAction
participant AttioApp
participant AttioAPI
User->>AttioAction: Trigger "Create Person" or "Update Person" or "Create Task"
AttioAction->>AttioApp: Call createRecord/updateRecord/postTask with user data
AttioApp->>AttioAPI: Send HTTP POST/PATCH to Attio endpoint
AttioAPI-->>AttioApp: Return API response
AttioApp-->>AttioAction: Return result
AttioAction-->>User: Output summary and data
sequenceDiagram
participant SourceComponent
participant BaseSource
participant AttioApp
participant AttioAPI
SourceComponent->>BaseSource: Activate (subscribe to events)
BaseSource->>AttioApp: createWebhook with subscriptions
AttioApp->>AttioAPI: POST /webhooks
AttioAPI-->>AttioApp: Webhook confirmation
AttioApp-->>BaseSource: Webhook created
BaseSource-->>SourceComponent: Ready to receive events
Assessment against linked issues
Suggested labels
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
components/attio/actions/create-note/create-note.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/attio/actions/create-person/create-person.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/attio/actions/create-task/create-task.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
✨ Finishing Touches
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. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
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: 2
🔭 Outside diff range comments (1)
components/attio/attio.app.mjs (1)
141-152
: 🛠️ Refactor suggestionRepeat the safe‑offset fix in every loader that paginates
To keep behaviour consistent, apply the
page ?? 0
guard (or default
page = 0
in the parameter list) to:
entryId.options()
– lines 147‑149attributeId.options()
– lines 180‑182Otherwise the first‑page lookup for those selectors can break.
Happy to open a small follow‑up PR if you like.Also applies to: 177-183
🧹 Nitpick comments (9)
components/attio/actions/create-task/create-task.mjs (1)
16-20
: Consider adding date validation for deadlineWhile the description explains the ISO 8601 format requirement, consider adding validation to ensure the provided date string is valid.
deadlineAt: { type: "string", label: "Deadline", description: "The deadline of the task in ISO 8601 format (e.g. `2025-04-22T10:00:00Z`)", + validate: (value) => { + if (!value) return true; + const date = new Date(value); + return !isNaN(date.getTime()) || "Please provide a valid ISO 8601 date string"; + }, },components/attio/sources/new-activity-created-instant/new-activity-created-instant.mjs (2)
9-9
: Consider starting with version 0.0.1.The component is using version 0.0.3 despite being newly introduced. Usually, new components start with version 0.0.1 and increment as changes are made.
- version: "0.0.3", + version: "0.0.1",
30-36
: Consider extracting repeated ID logic to a helper method.The same ID extraction logic is repeated three times in this method. Consider extracting it to improve readability and maintainability.
generateMeta(record) { + const activityId = record.id.task_id || record.id.note_id || record.id.comment_id; return { - id: record.id.task_id || record.id.note_id || record.id.comment_id, - summary: `New Activity with ID: ${record.id.task_id || record.id.note_id || record.id.comment_id}`, + id: activityId, + summary: `New Activity with ID: ${activityId}`, ts: Date.now(), }; },components/attio/actions/update-person/update-person.mjs (1)
110-218
: Consider shared utilities for common person record operations.This component shares significant code with the
create-person
action. Consider extracting the common data structuring logic into a shared utility function to improve maintainability.You could create a utility function in a common module that takes person fields and returns the structured data object, which both actions could then use.
components/attio/attio.app.mjs (5)
196-204
: ExposeAccept
andContent‑Type
defaults in one place
getHeaders()
hard‑codes onlyAuthorization
. Every Attio endpoint
expects JSON, so callers must remember to pass
headers: { "Content-Type": "application/json" }
each time. Consider
centralising the two defaults:getHeaders(headers) { return { ...headers, + "Accept": "application/json", + "Content-Type": "application/json", "Authorization": `Bearer ${this.$auth.oauth_access_token}`, }; },This removes repetition in the new action components.
214-237
: Method priority allows accidental override of HTTP verbThe helpers (
post
,patch
,put
,delete
) spread...args
after
the hard‑codedmethod
, letting callers silently override the verb.
A typo such asthis.post({ method: "GET", … })
would send a GET but
be named “post”, confusing for readers and log inspection.Move
method
to the end to make it authoritative:- post(args = {}) { - return this._makeRequest({ - method: "POST", - ...args, - }); + post(args = {}) { + return this._makeRequest({ + ...args, + method: "POST", + }); },Repeat for the other three helpers.
48-71
: Social profile props could share a single reusable definition
identical. Duplicating them bloats the component and invites
inconsistent edits later. A small helper cuts the noise:const socialProp = (platform, label = platform) => ({ type: "string", label: label.charAt(0).toUpperCase() + label.slice(1), description: `The person's ${label} profile URL.`, optional: true, }); linkedin: socialProp("linkedin"), twitter: socialProp("twitter", "Twitter handle"), facebook: socialProp("facebook"), instagram: socialProp("instagram"),Not mandatory, but keeps the file readable as more fields are added.
124-135
: Return{ label, value }
objects for better UXThe
listId
andentryId
loaders currently return bare strings for the
value, relying on Pipedream to auto‑label. Returning explicit objects
gives users readable dropdowns immediately — especially helpful for
entryId
, which today shows only UUIDs.-return data?.map(({ id: { entry_id: value } }) => value) || []; +return data?.map(({ id: { entry_id: value } }) => ({ + label: value, + value, +})) || [];Applies similarly to
entryId
and any other loader that returns raw
IDs.
238-243
: Add pagination tolistWorkspaceMembers
Large workspaces can have hundreds of members; the current call fetches
only the default page. The Attio API supportslimit
/offset
, so
exposepage
in the options loader and reuse the existing pagination
pattern.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (21)
components/attio/actions/create-note/create-note.mjs
(3 hunks)components/attio/actions/create-person/create-person.mjs
(1 hunks)components/attio/actions/create-task/create-task.mjs
(1 hunks)components/attio/actions/create-update-record/create-update-record.mjs
(1 hunks)components/attio/actions/delete-list-entry/delete-list-entry.mjs
(2 hunks)components/attio/actions/update-person/update-person.mjs
(1 hunks)components/attio/attio.app.mjs
(3 hunks)components/attio/common/constants.mjs
(1 hunks)components/attio/package.json
(1 hunks)components/attio/sources/common/base.mjs
(3 hunks)components/attio/sources/list-entry-deleted-instant/list-entry-deleted-instant.mjs
(2 hunks)components/attio/sources/list-entry-updated-instant/list-entry-updated-instant.mjs
(2 hunks)components/attio/sources/new-activity-created-instant/new-activity-created-instant.mjs
(1 hunks)components/attio/sources/new-activity-created-instant/test-event.mjs
(1 hunks)components/attio/sources/new-list-entry-instant/new-list-entry-instant.mjs
(2 hunks)components/attio/sources/new-note-instant/new-note-instant.mjs
(1 hunks)components/attio/sources/new-object-attribute-instant/new-object-attribute-instant.mjs
(1 hunks)components/attio/sources/new-record-created-instant/new-record-created-instant.mjs
(2 hunks)components/attio/sources/note-updated-instant/note-updated-instant.mjs
(1 hunks)components/attio/sources/object-attribute-updated-instant/object-attribute-updated-instant.mjs
(1 hunks)components/attio/sources/record-updated-instant/record-updated-instant.mjs
(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
components/attio/sources/common/base.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-07-24T02:06:47.016Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
- GitHub Check: Lint Code Base
- GitHub Check: Verify TypeScript components
🔇 Additional comments (46)
components/attio/common/constants.mjs (1)
1-18
: Well-structured constants module for Attio API integrationThis new constants module effectively centralizes important API configuration values like base URL, version path, and pagination limits. The
TARGET_OBJECT
enum provides a clean way to reference object types throughout the codebase.This approach follows best practices by:
- Eliminating hardcoded values across the integration
- Creating a single source of truth for API configuration
- Making future API endpoint or configuration changes easier to maintain
components/attio/sources/common/base.mjs (4)
11-15
: Good refactoring of webhook activation with subscription-based modelThe webhook activation method now uses the new
createWebhook
wrapper and a subscription-based model viagetSubscriptions()
instead of separate event type and filter methods. This approach is more modular and follows the pattern used in other Pipedream integrations.
22-27
: Good refactoring of webhook deactivation with wrapper methodThe deactivation hook now uses the new
deleteWebhook
wrapper method, which is consistent with the modular approach applied to the activation hook.
37-39
: Abstract method correctly implementedReplacing the previous abstract methods with a single
getSubscriptions()
method follows good object-oriented design principles. The error message correctly indicates that subclasses must implement this method.
43-56
: Well-implemented webhook wrapper methodsThe new
createWebhook
anddeleteWebhook
methods properly encapsulate the API calls to create and delete webhooks. They cleanly use the app's HTTP methods and handle path construction. This approach:
- Centralizes webhook management logic
- Makes the code more maintainable
- Follows the DRY principle by avoiding repetition in derived classes
components/attio/package.json (1)
3-3
: Appropriate version bump for feature additionsIncrementing the package version from 0.2.0 to 0.3.0 is appropriate given the significant additions (new components for creating/updating persons and tasks) and refactoring (webhook subscription model) in this PR.
components/attio/actions/create-update-record/create-update-record.mjs (1)
8-8
: Version incremented for consistencyThe action version has been incremented from "0.0.2" to "0.0.3", which maintains version consistency with other updated Attio components in this PR.
components/attio/sources/object-attribute-updated-instant/object-attribute-updated-instant.mjs (1)
9-21
: Clean architectural improvement for webhook subscription managementThe version increment and refactoring from
getEventType()
to the newgetSubscriptions()
method aligns with the broader architectural updates in the Attio integration. This new pattern provides more flexibility by allowing multiple subscriptions if needed in the future, and creates a more consistent approach across all source components.components/attio/sources/note-updated-instant/note-updated-instant.mjs (1)
9-21
: Consistent implementation of the subscription patternGood job maintaining consistency with the architectural pattern change. The version increment and implementation of the new
getSubscriptions()
method follows the same structure as other Attio source components, making the codebase more cohesive and easier to maintain.components/attio/sources/new-activity-created-instant/test-event.mjs (1)
1-16
: Well-structured test event for the new activity sourceThis test event provides a good representation of an Attio webhook payload for task creation events. The structure includes all necessary fields (webhook_id, event_type, workspace_id, task_id, and actor details), making it valuable for testing the new activity source component.
components/attio/sources/new-note-instant/new-note-instant.mjs (1)
9-21
: Systematic application of the new subscription patternThe version increment and replacement of
getEventType()
with the newgetSubscriptions()
method demonstrates a systematic approach to refactoring the Attio integration. This consistent implementation across all source components will make future maintenance and enhancements easier.components/attio/sources/new-object-attribute-instant/new-object-attribute-instant.mjs (2)
9-9
: Version bump is appropriateThe version increment from 0.0.1 to 0.0.2 is appropriate for this change since you're modifying the component's interface without changing its core functionality.
14-21
: Good refactoring of event subscriptionThe new
getSubscriptions()
method effectively replaces the previousgetEventType()
method, returning a structured subscription object instead. This approach is more flexible as it allows for multiple subscriptions if needed in the future.components/attio/sources/list-entry-deleted-instant/list-entry-deleted-instant.mjs (2)
9-9
: Version bump is appropriateThe version increment from 0.0.1 to 0.0.2 is appropriate for this change since you're modifying the component's interface without changing its core functionality.
23-38
: Good refactoring of event subscription and filterThe new
getSubscriptions()
method effectively combines the previousgetEventType()
andgetFilter()
methods into a single, more structured approach. This unification makes the code more maintainable and aligns with the refactoring pattern applied across other Attio components.components/attio/sources/new-record-created-instant/new-record-created-instant.mjs (2)
9-9
: Version bump is appropriateThe version increment from 0.0.2 to 0.0.3 is appropriate for this change since you're modifying the component's interface without changing its core functionality.
23-38
: Good refactoring of event subscription and filterThe new
getSubscriptions()
method effectively combines the previousgetEventType()
andgetFilter()
methods into a single, more structured approach. This makes the component consistent with the broader refactoring pattern across Attio source components.components/attio/sources/new-list-entry-instant/new-list-entry-instant.mjs (2)
9-9
: Version bump is appropriateThe version increment from 0.0.2 to 0.0.3 is appropriate for this change since you're modifying the component's interface without changing its core functionality.
23-38
: Good refactoring of event subscription and filterThe new
getSubscriptions()
method effectively combines the previousgetEventType()
andgetFilter()
methods into a single, more structured approach. This unification improves consistency across components and enables more flexible subscription management.components/attio/sources/list-entry-updated-instant/list-entry-updated-instant.mjs (2)
9-9
: Appropriate version incrementVersion has been correctly updated from 0.0.1 to 0.0.2 to reflect the interface changes in how webhook subscriptions are handled.
23-38
: Good refactoring to unified subscription modelThe change from separate
getEventType()
andgetFilter()
methods to a singlegetSubscriptions()
method improves modularity and aligns with the broader refactoring across multiple Attio source components. The subscription structure is well-organized and maintains the same filtering logic.components/attio/actions/create-task/create-task.mjs (2)
1-71
: Well-structured new action componentThis new "Create Task" action follows best practices for Pipedream components with clear prop definitions, appropriate documentation links, and concise methods. The component correctly implements the Attio API for task creation.
60-63
: Good handling of optional assigneesThe code correctly handles the case where assigneeIds might be undefined by using optional chaining and providing an empty array fallback.
components/attio/actions/delete-list-entry/delete-list-entry.mjs (4)
7-7
: Appropriate version incrementVersion has been correctly updated from 0.0.2 to 0.0.3 to reflect the interface changes in the component.
21-23
: Improved parameter destructuringThe simplification of the propDefinition callback with direct destructuring improves code readability.
27-36
: Good modularization with dedicated API methodAdding a dedicated
deleteListEntry
method improves code organization and follows the pattern used in other components. The method correctly constructs the API path and forwards additional options.
38-42
: Clean method invocationRun method now correctly uses the new dedicated method instead of directly calling the app's method, which is consistent with the overall refactoring approach.
components/attio/sources/record-updated-instant/record-updated-instant.mjs (2)
9-9
: Appropriate version incrementVersion has been correctly updated from 0.0.2 to 0.0.3 to reflect the interface changes in how webhook subscriptions are handled.
23-38
: Good refactoring to unified subscription modelThe change from separate methods to a single
getSubscriptions()
method improves consistency and aligns with the broader refactoring across Attio source components. The subscription structure effectively maintains the same filtering logic while providing a more organized approach to webhook event handling.components/attio/actions/create-note/create-note.mjs (7)
7-7
: Version increment looks appropriate.The version has been incremented from 0.0.2 to 0.0.3, which is appropriate given the refactoring and improvements made to this component.
15-23
: Good enhancement to the parentObject prop.The mapper function provides better UX by converting API values to more user-friendly display formats. This improves the component's usability by showing meaningful labels to users instead of raw API values.
25-26
: Improved prop labeling.The updated label and description are more clear and consistent with other components in the integration.
32-33
: Improved parameter naming.Changing from
objectId
totargetObject
provides better semantic clarity about what the parameter represents.
50-57
: Good modularization with methods object.Extracting API call logic into a dedicated method improves code organization and maintainability. This approach also makes the component more consistent with other Attio components.
59-59
: Refactored to use the dedicated createNote method.This change makes the code more maintainable by centralizing the API call logic in the methods section.
71-71
: Improved summary formatting.Using backticks around the ID improves readability in the output, making it easier to distinguish the ID from the rest of the text.
components/attio/sources/new-activity-created-instant/new-activity-created-instant.mjs (2)
4-11
: Nice addition of a unified activity source.This new component efficiently handles multiple activity types (notes, tasks, comments) in a single source, which provides a more streamlined way to track engagement activities.
14-29
: Well-structured subscription method.The
getSubscriptions
method clearly defines all the event types to listen for without any filters, making it easy to understand what events this source will emit.components/attio/actions/update-person/update-person.mjs (3)
4-9
: Great addition of an update person action.This well-structured action provides comprehensive options for updating existing person records in Attio.
12-29
: Well-designed recordId prop with custom mapper.The prop definition with custom mapper enhances usability by displaying meaningful person names instead of just IDs in the dropdown.
129-214
: Well-structured conditional data payload.The approach of conditionally including fields only when they're provided is clean and efficient. The nested structure correctly follows the Attio API's expected format.
components/attio/actions/create-person/create-person.mjs (5)
4-9
: Great addition of a create person action.This well-structured action provides comprehensive options for creating new person records in Attio.
12-89
: Well-organized props definitions.The props are well-organized with appropriate labels, descriptions, and leveraging reusable prop definitions from the Attio app.
108-193
: Well-structured API call with conditional data fields.The approach of conditionally including fields only when they're provided is clean and efficient. The structure correctly follows the Attio API's expected format.
195-195
: Good use of backticks in summary message.Using backticks around the ID improves readability in the output, making it easier to distinguish the ID from the rest of the text.
121-121
:⚠️ Potential issueFix syntax error in conditional spread operator.
There's a missing parenthesis in the logical condition that could cause unexpected behavior.
- ...(firstName || lastName) && { + ...((firstName || lastName) && {Likely an incorrect or invalid review comment.
ae31376
to
d6f541d
Compare
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.
Hi @jcortes I just added a minor suggestion. But I'm moving it to Ready for QA anyway
key: "attio-new-activity-created-instant", | ||
name: "New Activity Created (Instant)", | ||
description: "Emit new event when a note, task, or comment is created, useful for tracking engagement in real time.", | ||
version: "0.0.3", |
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.
version: "0.0.3", | |
version: "0.0.1", |
d6f541d
to
14a9d5b
Compare
14a9d5b
to
8861d86
Compare
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
♻️ Duplicate comments (1)
components/attio/attio.app.mjs (1)
72-104
: Fix potential NaN in offset calculationIn the
recordId
options function, the offset calculation can result in NaN if page is undefined.data: { limit: constants.DEFAULT_LIMIT, - offset: page * constants.DEFAULT_LIMIT, + offset: (page ?? 0) * constants.DEFAULT_LIMIT,
🧹 Nitpick comments (6)
components/attio/actions/create-task/create-task.mjs (3)
46-56
: Consider adding validation for linked record propertiesThe
linkedRecordPropsMapper
method assumes thatthis[
${prefix}targetObject]
andthis[
${prefix}targetRecordId]
exist, but there's no validation to handle cases where they might be undefined.linkedRecordPropsMapper(prefix) { const { [`${prefix}targetObject`]: targetObject, [`${prefix}targetRecordId`]: targetRecordId, } = this; + if (!targetObject || !targetRecordId) { + return {}; + } return { target_object: targetObject, target_record_id: targetRecordId, }; },
57-103
: Enhance record label fallback for better UXIn the
getLinkedRecordsPropDefinitions
method, there's a risk of displaying "undefined" labels if the name array exists but has no valid values.targetRecordOptions = data.map(({ id: { record_id: value }, values: { name }, }) => ({ value, - label: name[0]?.value || name[0]?.full_name || "unknown", + label: name && (name[0]?.value || name[0]?.full_name) || `Record ${value}`, }));
123-156
: Run method is well-structured but could use error handlingThe method effectively collects inputs, transforms them to the API format, and makes the API call. The export summary provides good feedback to the user.
Consider adding error handling to improve robustness:
async run({ $ }) { const { content, deadlineAt, isCompleted, assigneeIds, numberOfLinkedRecords, linkedRecordPropsMapper, } = this; + try { const response = await this.createTask({ $, data: { data: { format: "plaintext", content, deadline_at: deadlineAt, is_completed: isCompleted, assignees: assigneeIds?.map((id) => ({ referenced_actor_type: "workspace-member", referenced_actor_id: id, })) || [], linked_records: utils.getFieldsProps({ numberOfFields: numberOfLinkedRecords, fieldName: "linked record", propsMapper: linkedRecordPropsMapper, }), }, }, }); $.export("$summary", `Successfully created task with ID \`${response.data.id.task_id}\`.`); return response; + } catch (error) { + $.export("error", error); + throw `Failed to create task: ${error.message}`; + } },components/attio/actions/create-update-record/create-update-record.mjs (2)
55-87
: Remove commented-out codeThe commented-out
parseValues
function and filtering logic should be removed to keep the codebase clean.- // parseValues(attributes, values) { - // for (const [ - // key, - // value, - // ] of Object.entries(values)) { - // const { - // type, is_multiselect: isMultiselect, - // } = attributes.find(({ id }) => id.attribute_id === key); - // if (type === "checkbox") { - // values[key] = isMultiselect - // ? value.map((v) => !(v === "false" || v === "0")) - // : !(value === "false" || value === "0"); - // } - // if (type === "number" || type === "rating") { - // values[key] = isMultiselect - // ? value.map((v) => +v) - // : +value; - // } - // } - // return values; - // }, async getRelevantAttributes() { const stream = utils.paginate({ fn: this.attio.listAttributes, args: { objectId: this.objectId, }, }); const attributes = await utils.streamIterator(stream); return attributes.filter((a) => a.is_writable); - // return attributes.filter((a) => - // a.is_writable || (includeAttrId && a.id.attribute_id === this.attributeId)); },
89-103
: Remove debugging console.log statementThere's a console.log statement that should be removed before production.
async run({ $ }) { const { attio, - // parseValues, - // getRelevantAttributes, objectId, matchingAttribute, matchingAttributeValue, ...values } = this; - // const attributes = await getRelevantAttributes(); - - console.log("values!!!", JSON.stringify(values, null, 2));components/attio/attio.app.mjs (1)
105-122
: Improve workspaceMember label handlingThe workspaceMemberId options function could produce labels with extra spaces if firstName or lastName are undefined.
}) => ({ value, - label: `${firstName || ""} ${lastName || ""}`.trim(), + label: [firstName, lastName].filter(Boolean).join(" ") || `Member ${value}`, }),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (22)
components/attio/actions/create-note/create-note.mjs
(3 hunks)components/attio/actions/create-person/create-person.mjs
(1 hunks)components/attio/actions/create-task/create-task.mjs
(1 hunks)components/attio/actions/create-update-record/create-update-record.mjs
(4 hunks)components/attio/actions/delete-list-entry/delete-list-entry.mjs
(2 hunks)components/attio/actions/update-person/update-person.mjs
(1 hunks)components/attio/attio.app.mjs
(3 hunks)components/attio/common/constants.mjs
(1 hunks)components/attio/common/utils.mjs
(2 hunks)components/attio/package.json
(1 hunks)components/attio/sources/common/base.mjs
(3 hunks)components/attio/sources/list-entry-deleted-instant/list-entry-deleted-instant.mjs
(2 hunks)components/attio/sources/list-entry-updated-instant/list-entry-updated-instant.mjs
(2 hunks)components/attio/sources/new-activity-created-instant/new-activity-created-instant.mjs
(1 hunks)components/attio/sources/new-activity-created-instant/test-event.mjs
(1 hunks)components/attio/sources/new-list-entry-instant/new-list-entry-instant.mjs
(2 hunks)components/attio/sources/new-note-instant/new-note-instant.mjs
(1 hunks)components/attio/sources/new-object-attribute-instant/new-object-attribute-instant.mjs
(1 hunks)components/attio/sources/new-record-created-instant/new-record-created-instant.mjs
(2 hunks)components/attio/sources/note-updated-instant/note-updated-instant.mjs
(1 hunks)components/attio/sources/object-attribute-updated-instant/object-attribute-updated-instant.mjs
(1 hunks)components/attio/sources/record-updated-instant/record-updated-instant.mjs
(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/attio/common/constants.mjs
🚧 Files skipped from review as they are similar to previous changes (17)
- components/attio/package.json
- components/attio/sources/object-attribute-updated-instant/object-attribute-updated-instant.mjs
- components/attio/sources/new-record-created-instant/new-record-created-instant.mjs
- components/attio/sources/new-note-instant/new-note-instant.mjs
- components/attio/sources/new-list-entry-instant/new-list-entry-instant.mjs
- components/attio/sources/new-object-attribute-instant/new-object-attribute-instant.mjs
- components/attio/sources/list-entry-updated-instant/list-entry-updated-instant.mjs
- components/attio/sources/list-entry-deleted-instant/list-entry-deleted-instant.mjs
- components/attio/sources/note-updated-instant/note-updated-instant.mjs
- components/attio/actions/update-person/update-person.mjs
- components/attio/sources/common/base.mjs
- components/attio/sources/new-activity-created-instant/new-activity-created-instant.mjs
- components/attio/actions/create-note/create-note.mjs
- components/attio/actions/delete-list-entry/delete-list-entry.mjs
- components/attio/sources/new-activity-created-instant/test-event.mjs
- components/attio/sources/record-updated-instant/record-updated-instant.mjs
- components/attio/actions/create-person/create-person.mjs
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Publish TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
🔇 Additional comments (21)
components/attio/actions/create-task/create-task.mjs (4)
1-4
: Well-structured importsThe imports are clear and well-organized, following a logical structure by importing the app module first, followed by constants and utilities.
5-44
: Component definition and props look goodThe action is well-defined with appropriate metadata and clear property definitions. The properties have descriptive labels and helpful descriptions. Good job implementing the dynamic linked records functionality with
numberOfLinkedRecords
andreloadProps: true
.
104-109
: LGTM - Simple and clean task creation methodThe
createTask
method is well-implemented, using the app's POST method with the correct path and passing through any additional arguments.
111-122
: Well-implemented dynamic props generationThe
additionalProps
method effectively leverages the utility functions to generate dynamic linked record properties based on the specified count. This is a clean implementation of dynamic property generation.components/attio/common/utils.mjs (6)
1-2
: Clean import of constantsGood job centralizing constants in a separate module and importing them here.
38-41
: Nice utility for PascalCase conversionThe
toPascalCase
function is well-implemented using regex for string transformation, making it reusable across the codebase.
43-56
: Well-structured metadata property generatorThe
getMetadataProp
function effectively handles prefixes and labels with clean conditional expressions.
75-86
: LGTM - Clean implementation of fields props generatorThe
getFieldsProps
function provides a clean way to generate multiple field properties using Array mapping.
88-122
: Async property generator is well-implementedThe
getAdditionalProps
function effectively handles async operations with proper await chaining. The reduction pattern ensures props are accumulated correctly as promises resolve.
124-131
: LGTM - Clean exportsAll utility functions are properly exported for reuse throughout the codebase.
components/attio/actions/create-update-record/create-update-record.mjs (4)
8-8
: Significant version incrementThe version has been updated from 0.0.2 to 0.0.21, which is an unusually large increment. Consider documenting major changes in a changelog or comment.
18-34
: Improved record matching approachGood replacement of
attributeId
with the more descriptivematchingAttribute
andmatchingAttributeValue
props. This makes the record matching logic more explicit and easier to understand.
36-53
: Clean prop generation with simpler attribute filteringThe
additionalProps
method has been simplified to useapi_slug
instead ofattribute.id.attribute_id
and to filter only onis_writable
. This is a good improvement for maintainability.
104-120
: Improved record upsert structureThe revised structure for upsertRecord correctly uses the matching attribute parameters and simplifies the values object construction.
One suggestion: the
debug: true
flag might be meant for development and should probably be removed in production.const response = await attio.upsertRecord({ $, - debug: true, objectId, params: { matching_attribute: matchingAttribute, },
components/attio/attio.app.mjs (7)
1-2
: Good centralization of constantsImporting constants from a dedicated module is a great practice for maintainability.
8-71
: Comprehensive person-related property definitionsExcellent job creating detailed property definitions for person attributes. Each prop has clear labels, descriptions, and appropriate optional flags.
123-153
: Fix offset calculations in remaining options functionsThe same NaN issue exists in the
entryId
options function.params: { limit: constants.DEFAULT_LIMIT, - offset: page * constants.DEFAULT_LIMIT, + offset: (page ?? 0) * constants.DEFAULT_LIMIT,
170-193
: Same NaN issue in attributeId optionsThe offset calculation in attributeId options should also handle undefined page.
params: { limit: constants.DEFAULT_LIMIT, - offset: page * constants.DEFAULT_LIMIT, + offset: (page ?? 0) * constants.DEFAULT_LIMIT,
196-204
: Clean helper methods for URL and headersGood refactoring of URL and headers construction into dedicated helper methods for consistency and maintainability.
205-243
: Well-structured HTTP request methodsThe generic HTTP wrapper methods and API-specific methods are well-structured, promoting code reuse and consistency.
244-303
: Good organization of API methodsThe API methods are well-organized with consistent parameter destructuring and use of the generic HTTP wrappers.
function getFieldProps({ | ||
index, fieldName, prefix, | ||
propsMapper = function propsMapper(prefix) { | ||
const { [`${prefix}name`]: name } = this; | ||
return { | ||
name, | ||
}; | ||
}, | ||
} = {}) { | ||
const { prefix: metaPrefix } = getMetadataProp({ | ||
index, | ||
fieldName, | ||
prefix, | ||
}); | ||
return propsMapper(metaPrefix); | ||
} |
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
Fix context issue in default propsMapper
The default propsMapper
function references this
which may lead to unexpected behavior when not bound properly.
function getFieldProps({
index, fieldName, prefix,
- propsMapper = function propsMapper(prefix) {
- const { [`${prefix}name`]: name } = this;
- return {
- name,
- };
- },
+ propsMapper = (prefix, context) => {
+ const name = context?.[`${prefix}name`];
+ return {
+ name,
+ };
+ },
+ context,
} = {}) {
const { prefix: metaPrefix } = getMetadataProp({
index,
fieldName,
prefix,
});
- return propsMapper(metaPrefix);
+ return propsMapper(metaPrefix, context);
}
Also update the call in getFieldsProps
to pass the context:
function getFieldsProps({
- numberOfFields, fieldName, propsMapper, prefix,
+ numberOfFields, fieldName, propsMapper, prefix, context,
} = {}) {
return Array.from({
length: numberOfFields,
}).map((_, index) => getFieldProps({
index,
fieldName,
prefix,
propsMapper,
+ context,
}));
}
📝 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.
function getFieldProps({ | |
index, fieldName, prefix, | |
propsMapper = function propsMapper(prefix) { | |
const { [`${prefix}name`]: name } = this; | |
return { | |
name, | |
}; | |
}, | |
} = {}) { | |
const { prefix: metaPrefix } = getMetadataProp({ | |
index, | |
fieldName, | |
prefix, | |
}); | |
return propsMapper(metaPrefix); | |
} | |
// components/attio/common/utils.mjs | |
function getFieldProps({ | |
index, | |
fieldName, | |
prefix, | |
propsMapper = (prefix, context) => { | |
const name = context?.[`${prefix}name`]; | |
return { name }; | |
}, | |
context, | |
} = {}) { | |
const { prefix: metaPrefix } = getMetadataProp({ | |
index, | |
fieldName, | |
prefix, | |
}); | |
return propsMapper(metaPrefix, context); | |
} | |
function getFieldsProps({ | |
numberOfFields, | |
fieldName, | |
propsMapper, | |
prefix, | |
context, | |
} = {}) { | |
return Array.from({ length: numberOfFields }).map((_, index) => | |
getFieldProps({ | |
index, | |
fieldName, | |
prefix, | |
propsMapper, | |
context, | |
}) | |
); | |
} |
WHY
Resolves #16302
Summary by CodeRabbit
New Features
Improvements
Bug Fixes