-
Notifications
You must be signed in to change notification settings - Fork 5.5k
17984 xero #18071
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
17984 xero #18071
Conversation
…bumps and new features. Key changes include: - Bumped version to 0.4.0 for the Xero Accounting API package. - Added new actions for creating, updating, and deleting tracking categories and options. - Enhanced existing actions with improved error handling and response formatting. - Refactored code for better readability and maintainability, including consistent use of the xeroAccountingApi instance. - Updated utility functions and constants for better modularity. This update improves the overall functionality and usability of the Xero Accounting API integration.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
WalkthroughRefactors many Xero actions/sources to use a centralized xeroAccountingApi app client (object-parameter signatures), renames props to camelCase with tenantId propDefinitions, adds parseObject util and named constants, introduces tracking category CRUD and tracking option create/update/delete actions, and bumps many versions. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User as User Action
participant Action as Create Tracking Category Action
participant App as xeroAccountingApi App
participant Xero as Xero API
User->>Action: Provide tenantId, name, options[]
Action->>App: createTrackingCategory({ tenantId, data: { Name } })
App->>Xero: PUT /api.xro/2.0/TrackingCategories
Xero-->>App: TrackingCategoryID
loop For each option (if provided)
Action->>App: createTrackingOption({ tenantId, trackingCategoryId, data: { Name } })
App->>Xero: PUT /TrackingCategories/{id}/Options
Xero-->>App: TrackingOptionID
end
App-->>Action: Combined category + options
Action-->>User: Return response + $summary
sequenceDiagram
autonumber
participant Action as Update Tracking Option Action
participant App as xeroAccountingApi App
participant Xero as Xero API
Action->>App: updateTrackingOption({ tenantId, trackingCategoryId, trackingOptionId, data:{ Name, Status } })
App->>Xero: POST /TrackingCategories/{catId}/Options/{optId}
Xero-->>App: Updated Option
App-->>Action: Response
Action-->>User: Export $summary
Estimated code review effort🎯 5 (Critical) | ⏱️ ~90 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
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: 40
🔭 Outside diff range comments (6)
components/xero_accounting_api/actions/find-contact/find-contact.mjs (1)
99-107: Validate presence and exclusivity of search criteriaCurrently, you only enforce mutual exclusivity when “Create a new contact if not found” is “No”, and there’s no guard when neither
namenoraccountNumberis provided. This can lead to fetching all contacts unintentionally or ambiguous matches when both fields are passed with creation enabled.Recommend:
- Always enforce mutual exclusivity (regardless of
createContactIfNotFound).- Require at least one of
nameoraccountNumberto be provided.Apply this diff:
- if (createContactIfNotFound === "No" && accountNumber && name) { - throw new ConfigurationError( - "Choose exclusively between Account Number or Name to find a contact.", - ); - } + if (accountNumber && name) { + throw new ConfigurationError( + "Choose exclusively between Account Number or Name to find a contact.", + ); + } + if (!accountNumber && !name) { + throw new ConfigurationError( + "Provide either Account Number or Name to find a contact.", + ); + }components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs (1)
148-154: Address validation and payload bug: addressLine2 not considered and mis-assigned
addressEnteredchecksthis.addressLine1twice and never checksaddressLine2. This can incorrectly skip validation when only line 2 is provided.- In the payload,
AddressLine2is assignedthis.addressLine1instead ofthis.addressLine2.These cause incorrect validation and contact payload data.
Apply this diff:
- const addressEntered = this.addressLine1 - || this.addressLine1 + const addressEntered = this.addressLine1 + || this.addressLine2 || this.city || this.region || this.postalCode || this.country;- AddressLine2: this.addressLine1, + AddressLine2: this.addressLine2,Also applies to: 170-176
components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (1)
116-135: Payload still references old snake_case props — request will send mostly undefined fieldsThis breaks the action: nearly all fields map to undefined. Use the new camelCase props.
Apply this diff:
data: { - Type: "ACCPAY", //ACCPAY = Purchase Bill - Contact: { - ContactID: this.contact_id, - Name: this.contact_name, - }, - LineItems: this.line_items, - Date: this.date, - DueDate: this.due_date, - LineAmountTypes: this.line_amount_type, - InvoiceNumber: this.purchase_bill_number, - Reference: this.reference, - BrandingThemeID: this.branding_theme_id, - Url: this.url, - CurrencyCode: this.currency_code, - CurrencyRate: this.currency_rate, - Status: this.status, - SentToContact: this.sent_to_contact, - PlannedPaymentDate: this.planned_payment_date, + Type: "ACCPAY", // ACCPAY = Purchase Bill + Contact: { + ContactID: this.contactId, + Name: this.contactName, + }, + LineItems: this.lineItems, + Date: this.date, + DueDate: this.dueDate, + LineAmountTypes: this.lineAmountType, + InvoiceNumber: this.purchaseBillNumber, + Reference: this.reference, + BrandingThemeID: this.brandingThemeId, + Url: this.url, + CurrencyCode: this.currencyCode, + CurrencyRate: this.currencyRate, + Status: this.status, + SentToContact: this.sentToContact, + PlannedPaymentDate: this.plannedPaymentDate, },components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
196-223: Payload maps to snake_case props — data will be empty/incorrectAll fields should reference the newly introduced camelCase props. Current code sends undefineds.
Apply this diff:
data: { - Name: this.name, - ContactID: this.contact_id, - ContactNumber: this.contact_number, - AccountNumber: this.account_number, - ContactStatus: this.contact_status, - FirstName: this.first_name, - LastName: this.last_name, - EmailAddress: this.email_address, - SkypeUserName: this.skype_user_name, - ContactPersons: this.contact_persons, - BankAccountDetails: this.bank_account_details, - TaxNumber: this.tax_number, - AccountsReceivableTaxType: this.account_receivable_tax_type, - AccountsPayableTaxType: this.account_payable_type, - Addresses: this.addresses, - Phones: this.phones, - IsSupplier: this.is_supplier, - IsCustomer: this.is_customer, - DefaultCurrency: this.default_currency, - XeroNetworkKey: this.xero_network_key, - SalesDefaultAccountCode: this.sales_default_account_code, - PurchasesDefaultAccountCode: this.puchases_default_account_code, - SalesTrackingCategories: this.sales_tracking_categories, - PurchasesTrackingCategories: this.puechases_tracking_categories, - TrackingCategoryName: this.tracking_category_name, - TrackingOptionName: this.tracking_option_name, - PaymentTerms: this.payment_terms, + Name: this.name, + ContactID: this.contactId, + ContactNumber: this.contactNumber, + AccountNumber: this.accountNumber, + ContactStatus: this.contactStatus, + FirstName: this.firstName, + LastName: this.lastName, + EmailAddress: this.emailAddress, + SkypeUserName: this.skypeUserName, + ContactPersons: this.contactPersons, + BankAccountDetails: this.bankAccountDetails, + TaxNumber: this.taxNumber, + AccountsReceivableTaxType: this.accountReceivableTaxType, + AccountsPayableTaxType: this.accountPayableType, + Addresses: this.addresses, + Phones: this.phones, + IsSupplier: this.isSupplier, + IsCustomer: this.isCustomer, + DefaultCurrency: this.defaultCurrency, + XeroNetworkKey: this.xeroNetworkKey, + SalesDefaultAccountCode: this.salesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode, + SalesTrackingCategories: this.salesTrackingCategories, + PurchasesTrackingCategories: this.purchasesTrackingCategories, + TrackingCategoryName: this.trackingCategoryName, + TrackingOptionName: this.trackingOptionName, + PaymentTerms: this.paymentTerms, },components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (2)
196-229: Undefined variables in data payloadThe data payload references old snake_case variables that no longer exist after the camelCase refactoring. This will cause the update to fail or send undefined values.
data: { Name: this.name, - ContactID: this.contact_id, - ContactNumber: this.contact_number, - AccountNumber: this.account_number, - ContactStatus: this.contact_status, - FirstName: this.first_name, - LastName: this.last_name, - EmailAddress: this.email_address, - SkypeUserName: this.skype_user_name, - ContactPersons: this.contact_persons, - BankAccountDetails: this.bank_account_details, - TaxNumber: this.tax_number, - AccountsReceivableTaxType: this.account_receivable_tax_type, - AccountsPayableTaxType: this.account_payable_type, + ContactID: this.contactId, + ContactNumber: this.contactNumber, + AccountNumber: this.accountNumber, + ContactStatus: this.contactStatus, + FirstName: this.firstName, + LastName: this.lastName, + EmailAddress: this.emailAddress, + SkypeUserName: this.skypeUserName, + ContactPersons: this.contactPersons, + BankAccountDetails: this.bankAccountDetails, + TaxNumber: this.taxNumber, + AccountsReceivableTaxType: this.accountReceivableTaxType, + AccountsPayableTaxType: this.accountPayableType, Addresses: this.addresses, Phones: this.phones, - IsSupplier: this.is_supplier, - IsCustomer: this.is_customer, - DefaultCurrency: this.default_currency, - XeroNetworkKey: this.xero_network_key, - SalesDefaultAccountCode: this.sales_default_account_code, - PurchasesDefaultAccountCode: this.puchases_default_account_code, - SalesTrackingCategories: this.sales_tracking_categories, - PurchasesTrackingCategories: this.puechases_tracking_categories, - TrackingCategoryName: this.tracking_category_name, - TrackingOptionName: this.tracking_option_name, - PaymentTerms: this.payment_terms, + IsSupplier: this.isSupplier, + IsCustomer: this.isCustomer, + DefaultCurrency: this.defaultCurrency, + XeroNetworkKey: this.xeroNetworkKey, + SalesDefaultAccountCode: this.salesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode, + SalesTrackingCategories: this.salesTrackingCategories, + PurchasesTrackingCategories: this.purchasesTrackingCategories, + TrackingCategoryName: this.trackingCategoryName, + TrackingOptionName: this.trackingOptionName, + PaymentTerms: this.paymentTerms, },
222-224: Additional typo in data payloadThe data payload has typos that correspond to the property name typos:
puchases_default_account_codeshould use the corrected property name, andpuechases_tracking_categoriesshould also be corrected.This is already addressed in the previous fix for undefined variables, where we correct to:
PurchasesDefaultAccountCode: this.purchasesDefaultAccountCodePurchasesTrackingCategories: this.purchasesTrackingCategories
🧹 Nitpick comments (43)
components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (4)
107-107: Make the summary reflect create vs updateCurrently always says “Contact created successfully” even when updating. Use a dynamic summary.
- response && $.export("$summary", "Contact created successfully"); + response && $.export("$summary", `Contact ${contactID ? "updated" : "created"} successfully`);
6-6: Remove trailing space from action nameMinor polish: drop the trailing space to avoid inconsistent display in the UI.
- name: "Create or update contact ", + name: "Create or update contact",
37-37: Fix spacing before periodGrammar nit: remove the extra space before the period.
- description: "First name of contact person .", + description: "First name of contact person.",
55-55: Fix double period and hyphenate “User-defined”Minor grammar/style improvement.
- description: "User defined account number..", + description: "User-defined account number.",components/xero_accounting_api/actions/delete-tracking-category-option/delete-tracking-category-option.mjs (1)
49-51: Optional: return a consistent shape for delete actionsDelete endpoints often return 204/empty responses. Consider returning a simple success payload so downstream steps don’t have to handle undefined.
- $.export("$summary", `Successfully deleted tracking category option with ID: ${this.trackingOptionId}`); - return response; + $.export("$summary", `Successfully deleted tracking category option with ID: ${this.trackingOptionId}`); + return { + success: true, + trackingOptionId: this.trackingOptionId, + data: response, + };components/xero_accounting_api/actions/delete-tracking-category/delete-tracking-category.mjs (1)
5-9: Prefer Title Case for action name for consistencyMost actions in this package use Title Case for the
name(e.g., “Delete Tracking Category Option”). Consider aligning.Apply this small change:
- name: "Delete tracking category", + name: "Delete Tracking Category",components/xero_accounting_api/common/util.mjs (1)
111-135: Don’t drop falsy-but-valid values in parseObject
if (!obj) return undefined;treats0andfalseas “absent”. Prefer nullish check so valid falsy values are preserved.Apply this minimal fix:
-const parseObject = (obj) => { - if (!obj) return undefined; +const parseObject = (obj) => { + if (obj == null) return undefined;Optional: consider reusing
parseObjectwithinformatLineItemsto de-duplicate parsing and add resilience to malformed JSON (use try/catch similar toparseObject).components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
3-9: Nit: Title casing for nameConsider “Get Tracking Category” for consistency with other actions’ capitalization.
- name: "Get tracking category", + name: "Get Tracking Category",Also, please double-check the documentation anchor in the description resolves correctly.
components/xero_accounting_api/actions/find-contact/find-contact.mjs (1)
34-43: Inconsistent UX: boolean vs string for “Create if not found” across actionsThis action uses a string prop with “Yes/No”, while
find-or-create-contactuses a boolean. Aligning to boolean improves UX consistency and reduces string comparisons.Suggested minimal change:
- createContactIfNotFound: { - description: "Create a new contact if not found?.", - label: "Create a new contact if not found", - type: "string", - options: [ - "Yes", - "No", - ], - reloadProps: true, - }, + createContactIfNotFound: { + description: "Create a new contact if not found.", + label: "Create a new contact if not found", + type: "boolean", + reloadProps: true, + },Then update usages:
- if (this.createContactIfNotFound === "Yes") { + if (this.createContactIfNotFound) {- if (createContactIfNotFound === "No" && accountNumber && name) { + if (!createContactIfNotFound && accountNumber && name) {- if (createContactIfNotFound === "Yes") { + if (createContactIfNotFound) {- createContactIfNotFound === "Yes" + createContactIfNotFoundAlso applies to: 47-53, 99-103
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (2)
126-126: Error message references “Type” which isn’t user-provided here“Type” is hardcoded to “ACCREC” and not a required user input in this action. Adjust the message to avoid confusion.
- throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, **Type**, and **Line Items** parameters."); + throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, plus **Tenant ID** and **Line Items**.");
129-152: Payload restructuring to app method is correct; consider boolean handling forSentToContactand prop naming
- Using
{ $, tenantId, data }is correct. LGTM.- Minor:
sentToContactprop is typed as string but the Xero field expects boolean. Either change the prop type to boolean, or coerce here.Coerce to boolean non-destructively:
- SentToContact: this.sentToContact, + SentToContact: typeof this.sentToContact === "string" + ? this.sentToContact.toLowerCase() === "true" + : this.sentToContact,Also consider aligning the prop name
expectedPaymentDatatoexpectedPaymentDate. To avoid breaking change, support both:- ExpectedPaymentDate: this.expectedPaymentData, + ExpectedPaymentDate: this.expectedPaymentDate ?? this.expectedPaymentData,If desired, I can follow up with a PR to migrate the prop name and mark the old prop as deprecated in the description.
components/xero_accounting_api/actions/update-tracking-category/update-tracking-category.mjs (1)
7-7: Confirm documentation anchor targets the update endpointThe link currently points to the general tracking categories doc with the create anchor. Please verify the anchor for updating by ID (likely “…#post-trackingcategories-trackingcategoryid”) so users land on the right section.
components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
25-27: Redundant required-prop validation
tenantIdandinvoiceIdare required via props, so this runtime check is typically redundant. Consider removing to reduce noise.Apply this diff (optional):
- if (!this.tenantId || !this.invoiceId) { - throw new ConfigurationError("Must provide **Tenant ID**, and **Invoice ID** parameters."); - }components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
25-27: Redundant required-prop validationProps enforce required inputs; the runtime check is optional and can be removed to streamline code.
Apply this diff (optional):
- if (!this.tenantId || !this.contactIdentifier) { - throw new ConfigurationError("Must provide **Tenant ID**, and **Contact Identifier** parameters."); - }components/xero_accounting_api/actions/get-item/get-item.mjs (1)
25-27: Redundant required-prop validationGiven required props, this guard is optional. Removing it reduces boilerplate.
Apply this diff (optional):
- if (!this.tenantId || !this.itemId) { - throw new ConfigurationError("Must provide **Tenant ID**, and **Item ID** parameters."); - }components/xero_accounting_api/actions/get-bank-statements-report/get-bank-statements-report.mjs (2)
44-49: Build params without undefined valuesAvoid sending undefined query params. Only include dates if provided.
Apply this diff:
- params: { - bankAccountId: this.bankAccountId, - fromDate: this.fromDate, - toDate: this.toDate, - }, + params: { + bankAccountId: this.bankAccountId, + ...(this.fromDate !== undefined && { fromDate: this.fromDate }), + ...(this.toDate !== undefined && { toDate: this.toDate }), + },
26-33: Clarify expected date format in descriptionsSpecify the expected format (e.g., YYYY-MM-DD) to reduce user error when entering dates.
Apply this diff (optional):
- description: "Get the bank statements of the specified bank account from this date", + description: "Get the bank statements of the specified bank account from this date (YYYY-MM-DD)", @@ - description: "Get the bank statements of the specified bank account to this date", + description: "Get the bank statements of the specified bank account to this date (YYYY-MM-DD)",components/xero_accounting_api/actions/update-tracking-category-option/update-tracking-category-option.mjs (2)
7-7: Fix wording: This updates a tracking category option, not a categoryThe description should match the action’s intent (and file/key/name). Also consider using the specific docs anchor for options if available.
- description: "Update a tracking category by ID [See the documentation](https://developer.xero.com/documentation/api/accounting/trackingcategories#post-trackingcategories).", + description: "Update a tracking category option by ID [See the documentation](https://developer.xero.com/documentation/api/accounting/trackingcategories#post-trackingcategories).",
55-66: Don’t send undefined fields; build the payload conditionallyAvoid sending Status when it’s not provided. This reduces the chance of API validation issues and keeps the request minimal.
- const response = await this.xeroAccountingApi.updateTrackingOption({ - $, - tenantId: this.tenantId, - trackingCategoryId: this.trackingCategoryId, - trackingOptionId: this.trackingOptionId, - data: { - Name: this.optionName, - Status: this.status, - }, - }); + const data = { + Name: this.optionName, + ...(this.status && { Status: this.status }), + }; + + const response = await this.xeroAccountingApi.updateTrackingOption({ + $, + tenantId: this.tenantId, + trackingCategoryId: this.trackingCategoryId, + trackingOptionId: this.trackingOptionId, + data, + });components/xero_accounting_api/actions/email-an-invoice/email-an-invoice.mjs (1)
21-22: Fix typo in allowed status values in prop description“SUMBITTED” → “SUBMITTED”.
- description: "Xero generated unique identifier for the invoice to send by email out of Xero. The invoice must be of Type ACCREC and a valid Status for sending (SUMBITTED,AUTHORISED or PAID).", + description: "Xero generated unique identifier for the invoice to send by email out of Xero. The invoice must be of Type ACCREC and a valid Status for sending (SUBMITTED, AUTHORISED or PAID).",components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
21-22: Minor: capitalize “URL” in the prop descriptionAligns with conventional capitalization.
- description: "Xero generated unique identifier for the invoice to retrieve its online url.", + description: "Xero generated unique identifier for the invoice to retrieve its online URL.",components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs (2)
62-63: Confirm response shape; summary may not show IDXero often returns created entities inside an array (e.g.,
Employees[0].EmployeeID). IfcreateEmployeereturns that shape,response.EmployeeIDwill beundefined.Apply this defensive diff to support both shapes:
- $.export("$summary", `Successfully created employee with ID: ${response.EmployeeID}`); - return response; + const employeeId = response?.EmployeeID ?? response?.Employees?.[0]?.EmployeeID; + $.export("$summary", `Successfully created employee with ID: ${employeeId ?? "unknown"}`); + return response;Please confirm the shape returned by
xeroAccountingApi.createEmployeeand adjust if it’s guaranteed to be one or the other.
39-44: Validate External Link shape matches Xero expectationDocstring suggests only a URL is needed. Xero’s ExternalLink entity typically expects a nested object with a specific key (often
Url). Ensure callers pass{ Url: "https://..." }(or the expected shape) so Xero accepts the payload.components/xero_accounting_api/actions/get-bank-summary/get-bank-summary.mjs (1)
51-52: Optional: Improve summary contextConsider including the date range in the summary to aid observability.
- $.export("$summary", `Bank summary retrieved successfully: ${this.bankAccountId}`); + $.export("$summary", `Bank summary retrieved for ${this.bankAccountId}${this.fromDate || this.toDate ? ` (${this.fromDate || "…" } → ${this.toDate || "…"})` : ""}`);components/xero_accounting_api/actions/download-invoice/download-invoice.mjs (2)
42-47: Avoid base64 round-trip; use syncDir; add a $summaryThe current implementation converts the buffer to base64 and back, and ignores the
syncDirprop. Write the buffer directly and honorsyncDirwhen provided.- const invoicePdf = data.toString("base64"); - const buffer = Buffer.from(invoicePdf, "base64"); - const tmpDir = "/tmp"; - const invoicePath = `${tmpDir}/${this.invoiceId}.pdf`; - $.export("invoice_path", invoicePath); //This is where the invoice is saved at the workflow's temporary files. - fs.writeFileSync(invoicePath, buffer); + const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data); + const outDir = this.syncDir || "/tmp"; + const invoicePath = `${outDir}/${this.invoiceId}.pdf`; + $.export("invoice_path", invoicePath); // This is where the invoice is saved at the workflow's temporary files. + $.export("$summary", `Invoice ${this.invoiceId} saved to ${invoicePath}`); + fs.writeFileSync(invoicePath, buffer);
24-29: syncDir prop is unusedLeverage
syncDirfor the output path (see suggested diff above) or remove the prop to avoid confusion.components/xero_accounting_api/actions/create-history-note/create-history-note.mjs (1)
50-52: Add max-length guard for Details (<= 250 chars)Xero enforces 250 chars. Proactively validate to surface a clearer error before the API call.
if (!this.tenantId || !this.endpoint || !this.guid || !this.details) { throw new ConfigurationError("Must provide **Tenant ID**, **Endpoint**, **GUID**, and **Details** parameters."); } + if (this.details.length > 250) { + throw new ConfigurationError("Details must be 250 characters or fewer."); + }components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (2)
75-76: More informative summary (fallback when no identifier provided)Current summary prints
undefinedwhencontactIdentifieris omitted. Prefer a count-based fallback.- $.export("$summary", `Successfully fetched contacts with ID: ${this.contactIdentifier}`); + const count = response?.Contacts?.length ?? 0; + const descriptor = this.contactIdentifier ? `ID: ${this.contactIdentifier}` : `${count} contact(s)`; + $.export("$summary", `Successfully fetched contacts (${descriptor})`);
47-52: Minor:pageis numericConsider using
type: "integer"forpageto prevent accidental non-numeric input.page: { label: "Page", - type: "string", + type: "integer", description: "Up to 100 contacts will be returned per call when the page parameter is used e.g. page=1.", optional: true, },components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (3)
17-22: Fix description: references “contact” instead of “credit note” and “contact note” typoThe description mixes entities. It should refer to a credit note, not a contact/contact note.
Apply this diff:
- description: "Credit note identifier of the contact to get. Possible values: -* **CreditNoteID** - The Xero identifier for a contact note e.g. 297c2dc5-cc47-4afd-8ec8-74990b8761e9 -* **CreditNoteNumber** - Identifier for Credit Note CN-8743802", + description: "Identifier for the credit note to retrieve. Possible values: +* **CreditNoteID** — The Xero identifier for a credit note, e.g. 297c2dc5-cc47-4afd-8ec8-74990b8761e9 +* **CreditNoteNumber** — Identifier for a credit note, e.g. CN-8743802",
42-45: Consider numeric type for Page propXero’s page parameter is numeric. Using an integer type improves validation and UI.
- type: "string", + type: "integer",
61-62: Avoid “undefined” in summary when no identifier is providedMake the summary conditional so it reads cleanly without an identifier.
- $.export("$summary", `Successfully fetched credit notes with ID: ${this.creditNoteIdentifier}`); + $.export("$summary", `Successfully fetched credit notes${this.creditNoteIdentifier ? ` with identifier: ${this.creditNoteIdentifier}` : ""}`);components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
41-45: Headers prop description is outdated given tenantId handling by the appThe app wrapper should inject xero-tenant-id from tenantId. The current description instructs users to set it manually, which conflicts with the new approach.
- description: "Headers to send in the request. Must include header `xero-tenant-id` with Id of the organization tenant to use on the Xero Accounting API. See [Get Tenant Connections](https://pipedream.com/@sergio/xero-accounting-api-get-tenant-connections-p_OKCzOgn/edit) for a workflow example on how to pull this data.", + description: "Additional headers to include in the request. The `xero-tenant-id` header is derived from the Tenant ID prop.",components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (3)
32-33: Grammar nit: “Filter by an any element”Tighten the copy for the Where description.
- description: "Filter by an any element (*see [Filters](https://developer.xero.com/documentation/api/requests-and-responses#get-modified)*)", + description: "Filter by any element (*see [Filters](https://developer.xero.com/documentation/api/requests-and-responses#get-modified)*)",
42-45: Consider numeric type for Page propUse integer for better validation and UI affordances.
- type: "string", + type: "integer",
61-62: Avoid “undefined” in summary when no Manual Journal ID is providedMake the summary conditional.
- $.export("$summary", `Successfully fetched manual journals with ID: ${this.manualJournalId}`); + $.export("$summary", `Successfully fetched manual journals${this.manualJournalId ? ` with ID: ${this.manualJournalId}` : ""}`);components/xero_accounting_api/actions/create-item/create-item.mjs (1)
71-80: Unitdp could be numericOptional: make Unitdp an integer with numeric options to avoid string-to-number coercion downstream.
- unitdp: { - type: "string", + unitdp: { + type: "integer", label: "Unitdp", description: "By default UnitPrice is returned to two decimal places.", optional: true, options: [ - "2", - "4", + 2, + 4, ], },components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
96-97: $summary message is misleading; invoiceIdentifier isn’t an “ID”invoiceIdentifier selects which identifier field to filter on (e.g., InvoiceID or InvoiceNumber). Consider a neutral summary to avoid confusion.
Apply this diff:
- $.export("$summary", `Successfully fetched invoices with ID: ${this.invoiceIdentifier}`); + $.export("$summary", `Successfully fetched invoices${this.invoiceIdentifier ? ` with filter: ${this.invoiceIdentifier}` : ""}.`);components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (1)
24-29: Minor: Clarify description for Bank account IDThe text currently says “The ID of the Bank Account transaction,” which can confuse users.
Apply this diff:
- description: "The ID of the Bank Account transaction. If AccountID is not included then Code is required.", + description: "The ID of the Bank Account. If AccountID is not included then Code is required.",components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (1)
109-111: Validation message mentions Type, but Type isn’t a user prop hereType is fixed as "ACCPAY" in the payload, so it shouldn’t be listed as a required input.
Apply this diff:
- if ((!this.contactId && !this.contactName) || !this.tenantId || !this.lineItems) { - throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, **Type**, and **Line Items** parameters."); - } + if ((!this.contactId && !this.contactName) || !this.tenantId || !this.lineItems) { + throw new ConfigurationError( + "Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, and **Line Items**." + ); + }components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (2)
226-227: Make $summary resilient; prefer ID from response when contactId isn’t providedOn create-by-name flows, contactId may be empty. Use the API response when available.
Apply this diff:
- $.export("$summary", `Successfully created or updated contact with ID: ${this.contactId}`); - return response; + $.export("$summary", `Successfully created or updated contact with ID: ${response?.Contacts?.[0]?.ContactID || this.contactId || "unknown"}`); + return response;
100-105: Description for Account Payable Type appears incorrectIt mentions addresses; this prop maps to AccountsPayableTaxType. Consider updating the description to avoid confusion.
Suggested text: "Default tax type used for contact on AP invoices."
components/xero_accounting_api/xero_accounting_api.app.mjs (1)
88-98: Remove the unnecessary spread operator for theheadersparameterThe
headersparameter is already being spread in Line 105, so spreading it again on Line 93 is redundant.getHeader({ tenantId, modifiedSince = null, headers = {}, }) { const header = { "Authorization": `Bearer ${this.$auth.oauth_access_token}`, - ...headers, }; tenantId && (header["xero-tenant-id"] = tenantId); modifiedSince && (header["If-Modified-Since"] = modifiedSince); - return header; + return { + ...header, + ...headers, + }; },
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs
Outdated
Show resolved
Hide resolved
… improved data handling. Key changes include: - Integrated `formatLineItems` in `create-credit-note` and `create-purchase-bill` actions. - Implemented `parseObject` in `make-an-api-call`, `create-employee`, `create-or-update-contact`, and `update-contact` actions for better object parsing. - Updated property names for consistency across actions. These enhancements improve code maintainability and ensure consistent data formatting across API interactions.
…ke-an-api-call` method to directly return the axios call, simplifying the code and improving readability by removing unnecessary variable assignments.
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: 3
🔭 Outside diff range comments (4)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (2)
111-116:sentToContactshould be a boolean, not a stringThe description calls it a boolean, and Xero expects a boolean. Using a string risks sending invalid payloads.
- sentToContact: { - type: "string", + sentToContact: { + type: "boolean", label: "Sent To Contact", description: "Boolean to set whether the invoice in the Xero app should be marked as \"sent\". This can be set only on invoices that have been approved", optional: true, },
117-122: Fix typo:expectedPaymentData→expectedPaymentDate(+ backward compatibility in payload)Current prop name is inconsistent with the label and Xero field. Recommend renaming while keeping a fallback to avoid breaking existing uses.
- expectedPaymentData: { + expectedPaymentDate: { type: "string", label: "Expected Payment Date", description: "Shown on the sales invoices when this has been set", optional: true, },- SentToContact: this.sentToContact, - ExpectedPaymentDate: this.expectedPaymentData, + SentToContact: this.sentToContact, + ExpectedPaymentDate: this.expectedPaymentDate ?? this.expectedPaymentData,Also applies to: 149-151
components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
179-190: PaymentTerms shape is incorrect — must be an object (Bills/Sales with Day/Type)Xero expects:
- PaymentTerms: { Bills: { Day, Type }, Sales: { Day, Type } }
Providing a string will 400. Allow object input and parse.Apply this diff:
paymentTerms: { label: "Payment Terms", - type: "string", - description: "The default payment terms for the contact - see Payment Terms", + type: "any", + description: "The default payment terms for the contact. Provide a JSON object with Bills and/or Sales keys, each containing Day (number) and Type (DAYSAFTERBILLDATE, DAYSAFTERBILLMONTH, OFCURRENTMONTH, OFFOLLOWINGMONTH).", optional: true, options: [ "DAYSAFTERBILLDATE", "DAYSAFTERBILLMONTH", "OFCURRENTMONTH", "OFFOLLOWINGMONTH", ], },- PaymentTerms: this.paymentTerms, + PaymentTerms: parseObject(this.paymentTerms),Also applies to: 223-223
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
179-190: PaymentTerms shape mismatch; current string with enum options will fail against XeroXero’s PaymentTerms is an object (e.g., { Sales: { Day, Type }, Bills: { Day, Type } }), not a plain string. The current prop will not serialize correctly.
Update the prop to accept JSON/object and parse before sending:
paymentTerms: { label: "Payment Terms", - type: "string", - description: "The default payment terms for the contact - see Payment Terms", + type: "any", + description: "The default payment terms for the contact. Accepts an object or a JSON string with shape { Sales: { Day, Type }, Bills: { Day, Type } }. See Xero docs for supported Type values.", optional: true, - options: [ - "DAYSAFTERBILLDATE", - "DAYSAFTERBILLMONTH", - "OFCURRENTMONTH", - "OFFOLLOWINGMONTH", - ], },- PaymentTerms: this.paymentTerms, + PaymentTerms: parseObject(this.paymentTerms),Also applies to: 228-228
♻️ Duplicate comments (7)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (1)
27-29: Pass$togetContactoptions loader to preserve request contextOmitting
$can break client-level logging, headers, and rate limit handling.Apply this diff:
- const { Contacts: contacts } = await this.xero.getContact({ - tenantId: this.tenantId, - }); + const { Contacts: contacts } = await this.xero.getContact({ + $, + tenantId: this.tenantId, + });components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (2)
149-154: Prop key typo: puchasesDefaultAccountCode → purchasesDefaultAccountCodeThis is a public prop name; keeping the typo will lock users into a misspelling. Fix both the prop and the mapping.
Apply this diff:
- puchasesDefaultAccountCode: { + purchasesDefaultAccountCode: { label: "Purchases Default Account Code", type: "string", description: "The default purchases [account code](https://developer.xero.com/documentation/api/accounts) for contacts", optional: true, },- PurchasesDefaultAccountCode: this.puchasesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode,To catch any other usages of the misspelling across the repo, run:
#!/bin/bash rg -nP -C2 '\bpuchasesDefaultAccountCode\b|\bpuchases\b'Also applies to: 218-218
161-166: Prop key typo: puechasesTrackingCategories → purchasesTrackingCategoriesSame issue as the previous typo. Fix the public prop and the mapping.
Apply this diff:
- puechasesTrackingCategories: { + purchasesTrackingCategories: { label: "Purchases Tracking Categories", type: "string", description: "The default purchases [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", optional: true, },- PurchasesTrackingCategories: this.puechasesTrackingCategories, + PurchasesTrackingCategories: this.purchasesTrackingCategories,To verify there aren’t other misspellings, run:
#!/bin/bash rg -nP -C2 '\bpuechasesTrackingCategories\b|\bpuechases\b'Also applies to: 220-220
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
149-154: Fix typos in purchases props and usage (puchases/puechases → purchases)*These misspellings leak into the public action props and can confuse/break consumers. Please correct the prop keys and update their usage in the payload.
Apply:
- puchasesDefaultAccountCode: { + purchasesDefaultAccountCode: { label: "Purchases Default Account Code", type: "string", description: "The default purchases [account code](https://developer.xero.com/documentation/api/accounts) for contacts", optional: true, },- puechasesTrackingCategories: { + purchasesTrackingCategories: { label: "Purchases Tracking Categories", type: "string", description: "The default purchases [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", optional: true, },- PurchasesDefaultAccountCode: this.puchasesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode, - PurchasesTrackingCategories: this.puechasesTrackingCategories, + PurchasesTrackingCategories: this.purchasesTrackingCategories,Backward compatibility suggestion (optional, to avoid a breaking change): accept both old and new prop names and prefer the new ones when both are provided:
// place before constructing the `data` object const purchasesDefaultAccountCode = this.purchasesDefaultAccountCode ?? this.puchasesDefaultAccountCode; const purchasesTrackingCategories = this.purchasesTrackingCategories ?? this.puechasesTrackingCategories;Then use the local variables in the payload.
Also, please propagate the same fix across related actions (e.g., create-or-update-contact) to keep the surface consistent.
Run this to find other occurrences across the repo:
#!/bin/bash rg -n -C2 -P 'puechasesTrackingCategories|puchasesDefaultAccountCode'Also applies to: 161-166, 223-225
components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (2)
139-140: Fix summary: Xero returns an Invoices array for ACCPAYPurchase bills (ACCPAY) are returned under
Invoices.PurchaseBillIDdoesn’t exist; useInvoices[0].InvoiceIDwith a safe fallback.Apply this diff:
- $.export("$summary", `Successfully created purchase bill with ID: ${response.PurchaseBillID}`); - return response; + $.export("$summary", `Successfully created purchase bill with ID: ${response?.Invoices?.[0]?.InvoiceID || response?.InvoiceID || "unknown"}`); + return response;
96-101: Use boolean type for sentToContact propThe description and Xero API expect a boolean, not a string.
Apply this diff:
sentToContact: { label: "Sent to Contact", - type: "string", - description: "Boolean to set whether the invoice in the Xero app should be marked as \"sent\". This can be set only on invoices that have been approved", + type: "boolean", + description: "Set to true to mark the invoice as sent (only applies to approved invoices).", optional: true, },components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs (1)
77-82: Correct prop type for lineItemsThis should be an array, not a single object. Other actions use a
string[]of JSON strings parsed at runtime viaformatLineItems.Apply this diff:
lineItems: { - label: "Line items", - type: "object", - description: "See [Invoice Line Items](https://developer.xero.com/documentation/api/Invoices#LineItems)", - optional: true, + label: "Line items", + type: "string[]", + description: "Provide one or more line items as JSON strings. See https://developer.xero.com/documentation/api/Invoices#LineItems", + optional: true, },Runtime is already using
formatLineItems(this.lineItems), so this aligns the schema with the implementation.
🧹 Nitpick comments (16)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (4)
126-126: Fix validation message: remove “Type” (not a prop)
The action hardcodes Type to “ACCREC”; the error message mentions a non-existent input.- throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, **Type**, and **Line Items** parameters."); + throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, and **Line Items**.");
132-151: Avoid sending undefined/null fields to Xero (filter payload)
Reduce payload noise and align with patterns used in other actions by stripping null/undefined fields fromdata.Option A (no imports needed, inline filter):
- data: { + data: Object.fromEntries(Object.entries({ Type: "ACCREC", //ACCREC = Sales Invoice Contact: { ContactID: this.contactId, Name: this.contactName, }, LineItems: formatLineItems(this.lineItems), Date: this.date, DueDate: this.dueDate, LineAmountTypes: this.lineAmountType, InvoiceNumber: this.invoiceNumber, Reference: this.reference, BrandingThemeID: this.brandingThemeId, Url: this.url, CurrencyCode: this.currencyCode, CurrencyRate: this.currencyRate, Status: this.status, SentToContact: this.sentToContact, - ExpectedPaymentDate: this.expectedPaymentData, - }, + ExpectedPaymentDate: this.expectedPaymentDate ?? this.expectedPaymentData, + }).filter(([, v]) => v !== undefined && v !== null)),Option B (preferred, if a shared
removeNullEntriesutil is available in your codebase; import as appropriate):- data: { + data: removeNullEntries({ Type: "ACCREC", //ACCREC = Sales Invoice Contact: { ContactID: this.contactId, Name: this.contactName, }, LineItems: formatLineItems(this.lineItems), Date: this.date, DueDate: this.dueDate, LineAmountTypes: this.lineAmountType, InvoiceNumber: this.invoiceNumber, Reference: this.reference, BrandingThemeID: this.brandingThemeId, Url: this.url, CurrencyCode: this.currencyCode, CurrencyRate: this.currencyRate, Status: this.status, SentToContact: this.sentToContact, - ExpectedPaymentDate: this.expectedPaymentData, - }, + ExpectedPaymentDate: this.expectedPaymentDate ?? this.expectedPaymentData, + }),
63-68: Consider constraininglineAmountTypeto allowed values
To prevent invalid inputs, provide options (e.g., “Exclusive”, “Inclusive”, “NoTax”) or validate inrun.
3-3: Nit: align app prop naming with adjacent actions (“xeroAccountingApi”)
Other files often usexeroAccountingApias the prop name. This file usesxero. Consider standardizing for consistency across actions.components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (4)
95-106: Fix AR/AP tax type labels and descriptions (copy/paste errors)
- Accounts Receivable description incorrectly says “AP invoices”.
- Accounts Payable field label misses “Tax” and description references addresses.
Apply this diff:
accountReceivableTaxType: { label: "Account Receivable Tax Type", type: "string", - description: "Default tax type used for contact on AP invoices", + description: "Default tax type used for contact on AR invoices", optional: true, }, accountPayableType: { - label: "Account Payable Type", + label: "Accounts Payable Tax Type", type: "string", - description: "Store certain address types for a contact - see address types", + description: "Default tax type used for contact on AP invoices", optional: true, },
119-130: Replace stray control character in descriptions (use hyphen instead)The “Is Supplier/Is Customer” descriptions contain a stray “�” character.
Apply this diff:
isSupplier: { label: "Is Supplier", type: "boolean", - description: "true or false � Boolean that describes if a contact that has any AP invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts payable invoice is generated against this contact.", + description: "true or false - Boolean that describes if a contact that has any AP invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts payable invoice is generated against this contact.", optional: true, }, isCustomer: { label: "Is Customer", type: "boolean", - description: "true or false � Boolean that describes if a contact has any AR invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts receivable invoice is generated against this contact.", + description: "true or false - Boolean that describes if a contact has any AR invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts receivable invoice is generated against this contact.", optional: true, },
191-196: Preflight validation: require either contactId or nameFor a better UX, fail early if both are missing. If the app client already throws a ConfigurationError, feel free to skip this. Otherwise, add:
async run({ $ }) { + if (!this.contactId && !this.name) { + throw new ConfigurationError("Either contactId or name is required when creating or updating a contact."); + } const response = await this.xeroAccountingApi.createOrUpdateContact({And add this import at the top of the file:
import { ConfigurationError } from "@pipedream/platform";
227-228: Use returned ContactID in summary (fallback to input)this.contactId may be undefined for creates. Prefer the API response.
Apply this diff:
- $.export("$summary", `Successfully created or updated contact with ID: ${this.contactId}`); - return response; + const id = response?.Contacts?.[0]?.ContactID || this.contactId; + $.export("$summary", `Successfully created or updated contact with ID: ${id}`); + return response;components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (3)
95-106: Fix labels/descriptions for receivable/payable tax type props; consider consistent naming
- Labels: use “Accounts” (plural) and include “Tax Type”.
- Descriptions: AR vs AP are currently reversed/irrelevant.
Apply the label/description fixes:
- accountReceivableTaxType: { - label: "Account Receivable Tax Type", + accountReceivableTaxType: { + label: "Accounts Receivable Tax Type", type: "string", - description: "Default tax type used for contact on AP invoices", + description: "Default tax type used for contact on AR invoices.", optional: true, }, - accountPayableType: { - label: "Account Payable Type", + accountPayableType: { + label: "Accounts Payable Tax Type", type: "string", - description: "Store certain address types for a contact - see address types", + description: "Default tax type used for contact on AP invoices.", optional: true, },Optional follow-up: for consistency with the payload keys, consider renaming the props to accountsReceivableTaxType and accountsPayableTaxType. If you do, keep backward compatibility by accepting both names and preferring the new ones.
119-130: IsSupplier/IsCustomer are read-only in Xero; avoid sending them or clearly mark as read-onlyThese fields are not settable via the API. Sending them may be ignored or could cause validation errors depending on Xero behavior.
- Update descriptions to clearly state “Read-only; cannot be set via this action.”
- Prefer removing them from the payload.
Apply:
isSupplier: { label: "Is Supplier", type: "boolean", - description: "true or false � Boolean that describes if a contact that has any AP invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts payable invoice is generated against this contact.", + description: "Read-only. Boolean indicating if the contact has any AP invoices. Cannot be set via this action; it is automatically set when an accounts payable invoice is generated against this contact.", optional: true, }, isCustomer: { label: "Is Customer", type: "boolean", - description: "true or false � Boolean that describes if a contact has any AR invoices entered against them. Cannot be set via PUT or POST - it is automatically set when an accounts receivable invoice is generated against this contact.", + description: "Read-only. Boolean indicating if the contact has any AR invoices. Cannot be set via this action; it is automatically set when an accounts receivable invoice is generated against this contact.", optional: true, },- IsSupplier: this.isSupplier, - IsCustomer: this.isCustomer, + // IsSupplier/IsCustomer are read-only in Xero; do not sendAlso applies to: 218-219
66-76: Minor: update email description and remove legacy characterIf possible, drop the note about “umlauts not supported” (legacy limitation) and ensure no non-ASCII control characters slip into descriptions elsewhere.
components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (3)
110-112: Clarify validation error message (remove non-existent “Type”)This action hardcodes
Type: "ACCPAY"and has notypeprop. The error text should not mention “Type”.Apply this diff:
- if ((!this.contactId && !this.contactName) || !this.tenantId || !this.lineItems) { - throw new ConfigurationError("Must provide one of **Contact ID** or **Contact Name**, **Tenant ID**, **Type**, and **Line Items** parameters."); - } + if ((!this.contactId && !this.contactName) || !this.tenantId || !this.lineItems) { + throw new ConfigurationError("Must provide one of Contact ID or Contact Name, Tenant ID, and Line Items."); + }
31-35: Narrow prop type for lineItems and clean up description
formatLineItemssupports string arrays (JSON per line item) or arrays of objects, but usinganyweakens validation and UI. Recommendstring[]to align with similar actions and clarify the “at least one” requirement (remove stray markdown).Apply this diff:
- lineItems: { - label: "Line Items", - type: "any", - description: "See [LineItems](https://developer.xero.com/documentation/api/invoices#LineItemsPOST). The LineItems collection can contain any number of individual LineItem sub-elements. At least * **one** * is required to create a complete Invoice.", - }, + lineItems: { + label: "Line Items", + type: "string[]", + description: "Provide one or more line items as JSON strings. See https://developer.xero.com/documentation/api/invoices#LineItemsPOST", + },Note:
formatLineItems(this.lineItems)already parses string arrays, so no runtime change required.
48-53: Provide options for lineAmountTypeAdding explicit options improves UX and prevents invalid values.
Apply this diff:
lineAmountType: { label: "Line Amount Type", type: "string", description: "Line amounts are exclusive of tax by default if you don't specify this element. See [Line Amount Types](https://developer.xero.com/documentation/api/types#LineAmountTypes)", optional: true, + options: [ + "Exclusive", + "Inclusive", + "NoTax", + ], },components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs (2)
31-36: Fix copy: “this name” → “this number” in Contact Number descriptionMinor text fix to avoid confusion.
Apply this diff:
contactNumber: { type: "string", label: "Contact Number", - description: "Number of the contact associated to the credit note. If there is no contact matching this name, a new contact is created.", + description: "Number of the contact associated to the credit note. If there is no contact matching this number, a new contact is created.", optional: true, },
153-155: Harden summary extraction with safe fallbackAvoid possible runtime errors on unexpected responses or empty arrays.
Apply this diff:
- $.export("$summary", `Successfully created credit note with ID: ${response.CreditNotes[0].CreditNoteID}`); - return response; + $.export("$summary", `Successfully created credit note with ID: ${response?.CreditNotes?.[0]?.CreditNoteID || "unknown"}`); + return response;
📜 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 selected for processing (7)
components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs(4 hunks)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs(2 hunks)components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs(2 hunks)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs(3 hunks)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs(3 hunks)components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs(1 hunks)components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-10-08T16:42:59.225Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14229
File: components/americommerce/actions/update-customer/update-customer.mjs:89-94
Timestamp: 2024-10-08T16:42:59.225Z
Learning: When defining boolean properties in AmeriCommerce components (e.g., in `update-customer.mjs`), ensure that the label and description are consistent and clearly indicate the intent, especially when using negations like "No Account", to avoid confusion.
Applied to files:
components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjscomponents/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
PR: PipedreamHQ/pipedream#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/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjscomponents/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs
🧬 Code Graph Analysis (6)
components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (13)
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(59-66)components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs (1)
response(52-61)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(193-225)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(197-230)components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (1)
response(129-152)components/xero_accounting_api/actions/add-line-item-to-invoice/add-line-item-to-invoice.mjs (1)
response(38-45)components/xero_accounting_api/actions/create-history-note/create-history-note.mjs (1)
response(54-66)components/xero_accounting_api/actions/create-payment/create-payment.mjs (1)
response(160-164)components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(102-106)components/xero_accounting_api/actions/delete-tracking-category-option/delete-tracking-category-option.mjs (1)
response(42-47)components/xero_accounting_api/actions/delete-tracking-category/delete-tracking-category.mjs (1)
response(30-34)components/xero_accounting_api/common/util.mjs (1)
formatLineItems(22-40)
components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs (4)
components/xero_accounting_api/actions/create-item/create-item.mjs (1)
response(87-104)components/xero_accounting_api/actions/create-payment/create-payment.mjs (1)
response(160-164)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(102-106)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (3)
components/xero_accounting_api/sources/new-updated-contact/new-updated-contact.mjs (1)
contacts(37-42)components/xero_accounting_api/actions/add-line-item-to-invoice/add-line-item-to-invoice.mjs (1)
response(38-45)components/xero_accounting_api/common/util.mjs (1)
formatLineItems(22-40)
components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (13)
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(59-66)components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs (1)
response(52-61)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(197-230)components/xero_accounting_api/actions/xero-create-purchase-bill/xero-create-purchase-bill.mjs (1)
response(114-137)components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (1)
response(129-152)components/xero_accounting_api/actions/add-line-item-to-invoice/add-line-item-to-invoice.mjs (1)
response(38-45)components/xero_accounting_api/actions/create-history-note/create-history-note.mjs (1)
response(54-66)components/xero_accounting_api/actions/create-payment/create-payment.mjs (1)
response(160-164)components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(102-106)components/xero_accounting_api/actions/delete-tracking-category-option/delete-tracking-category-option.mjs (1)
response(42-47)components/xero_accounting_api/actions/delete-tracking-category/delete-tracking-category.mjs (1)
response(30-34)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (3)
components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(193-225)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(102-106)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs (4)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (1)
response(129-152)components/xero_accounting_api/actions/create-payment/create-payment.mjs (1)
response(160-164)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(102-106)components/xero_accounting_api/common/util.mjs (1)
formatLineItems(22-40)
⏰ 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). (5)
- GitHub Check: Ensure component commits modify component versions
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
- GitHub Check: Lint Code Base
- GitHub Check: pnpm publish
🔇 Additional comments (12)
components/xero_accounting_api/actions/xero-create-sales-invoice/xero-create-sales-invoice.mjs (2)
94-104: Verify numeric fields typed as strings
currencyRateis numeric in Xero. Keeping it a string might be intentional for high-precision decimals, but confirm consistency across actions and UI.Would you like me to scan the repo and list all places where numeric Xero fields are typed as “string” to standardize them (or justify exceptions)?
129-133: Good migration to object-style client call and nested payload
Switching tocreateInvoice({ $, tenantId, data })aligns with the new client interface and improves readability.components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
1-2: Good migration to app client + consistent payload shapingUses the shared Xero app client and parseObject for nested fields, and passes tenantId explicitly. This aligns with the PR-wide refactor and improves maintainability.
Also applies to: 191-225
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
1-3: Solid migration to app client + propDefinition wiring
- Imports and propDefinition usage look correct.
- Validation for tenantId/contactId and the switch to xeroAccountingApi.updateContact are sound.
- Summary export is helpful.
Also applies to: 12-18, 192-201, 232-233
components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs (1)
101-106: SentToContact is writable now — do not remove; update the description and keep sending itShort: Xero changed this field (changelog / xero-node v9.2.0). SentToContact is writable for credit notes since 26 Aug 2024 — the original suggestion to stop sending it is outdated.
Files to update:
- components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs — lines 101-106: update the description that currently says "currently read only".
- components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs — line ~147: keep sending SentToContact in the payload (do not apply the diff that removes it). Verify the property name/casing matches Xero's API.
Suggested change (replace description):
@@ components/xero_accounting_api/actions/create-credit-note/create-credit-note.mjs - description: "Boolean to indicate if a credit note has been sent to a contact via the Xero app (currently read only)", + description: "Boolean to indicate if a credit note has been sent to a contact via the Xero app. Writable via the Xero API (writable since 26 Aug 2024); ensure SDK/API version supports this.",Recommendation: ensure consumers use an SDK/API version that supports this (xero-node >= 9.2.0 / updated API); if you must support older integrations, add a graceful guard or feature flag.
Likely an incorrect or invalid review comment.
components/xero_accounting_api/actions/xero-accounting-create-employee/xero-accounting-create-employee.mjs (7)
1-3: LGTM! Clean migration to centralized app pattern.The imports properly migrate from direct API calls to the centralized xero app client, adding necessary utility functions and error handling. The ConfigurationError import aligns with the improved validation pattern used across the Xero actions.
12-18: LGTM! Consistent app integration pattern.The prop definition correctly uses the centralized xeroAccountingApi app and leverages its propDefinition for tenantId. This aligns with the broader migration pattern seen across other Xero actions in the PR.
19-28: LGTM! Props correctly migrated to camelCase.The firstName and lastName props are properly defined with camelCase naming, which fixes the previous snake_case issue that would have caused undefined values in the API payload.
40-45: LGTM! Consistent naming and typing.The externalLink prop uses camelCase naming consistently and maintains the correct object type for complex data structures.
48-50: LGTM! Improved validation with proper error handling.The validation logic correctly checks the camelCase property names and uses ConfigurationError for consistent error handling across the Xero actions.
52-61: LGTM! Proper API call migration and payload construction.The implementation correctly:
- Uses the centralized xeroAccountingApi.createEmployee method
- Maps camelCase props to the expected API payload keys (FirstName, LastName, ExternalLink)
- Applies parseObject utility to handle complex ExternalLink data
- Follows the established pattern from other migrated actions
This resolves the previous issue where snake_case property accessors would have sent undefined values to the API.
63-64: LGTM! Consistent response handling.The success message and return pattern align with other migrated Xero actions, providing clear feedback about the created employee.
...ctions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs
Show resolved
Hide resolved
...ctions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs
Show resolved
Hide resolved
...ero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs
Show resolved
Hide resolved
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
♻️ Duplicate comments (10)
components/xero_accounting_api/xero_accounting_api.app.mjs (10)
117-121: Use template literal for URL construction (style consistency)Adopt the established template literal pattern for URL concatenation.
getTenantConnections() { return this._makeRequest({ - url: BASE_URL + "/connections", + url: `${BASE_URL}/connections`, }); },
187-193: Normalize HTTP verb casing in createInvoiceUse "POST" to be consistent. Lowercase likely works, but consistency helps readability and avoids surprises.
createInvoice(opts = {}) { return this._makeRequest({ - method: "post", + method: "POST", path: "/Invoices", ...opts, }); },
206-210: Normalize HTTP verb casing in emailInvoiceUse "POST" to be consistent across methods.
return this._makeRequest({ - method: "post", + method: "POST", path: `/Invoices/${invoiceId}/Email`, ...opts, });
377-381: Normalize HTTP verb casing in uploadFileUse "POST" to match the rest of the codebase.
return this._makeRequest({ - method: "post", + method: "POST", path: `/${documentType}/${documentId}/Attachments/${fileName}`, ...opts, });
57-62: Guard against missing TrackingCategory/Options to avoid runtime crashIf the tracking category isn’t found or has no Options,
trackingCategories[0].Optionswill throw. Return an empty array in those cases.Apply this diff:
- return trackingCategories[0].Options.map(({ - TrackingOptionID, Name, - }) => ({ - label: Name, - value: TrackingOptionID, - })); + const trackingCategory = trackingCategories?.[0]; + const options = Array.isArray(trackingCategory?.Options) + ? trackingCategory.Options + : []; + return options.map(({ TrackingOptionID, Name }) => ({ + label: Name, + value: TrackingOptionID, + }));
168-174: Fix HTTP verb casing and path case for Contacts creation
- Use "POST" to match HTTP verb casing used elsewhere.
- Xero endpoints are case-sensitive; use
/Contacts(capital C) for consistency with other methods and to avoid 404s.createContact(opts = {}) { return this._makeRequest({ - method: "post", - path: "/contacts", + method: "POST", + path: "/Contacts", ...opts, }); },
342-349: Fix listContacts: collection endpoint should not accept identifierThis implementation fetches a single contact. Listing should call
/Contactsand accept only options.- listContacts({ - contactIdentifier, ...opts - }) { - return this._makeRequest({ - path: `/Contacts/${contactIdentifier}`, - ...opts, - }); - }, + listContacts(opts = {}) { + return this._makeRequest({ + path: `/Contacts`, + ...opts, + }); + },
350-357: Fix listCreditNotes: collection endpoint should not accept identifierThis fetches a single credit note; adjust to call
/CreditNoteswithout an identifier.- listCreditNotes({ - creditNoteIdentifier, ...opts - }) { - return this._makeRequest({ - path: `/CreditNotes/${creditNoteIdentifier}`, - ...opts, - }); - }, + listCreditNotes(opts = {}) { + return this._makeRequest({ + path: `/CreditNotes`, + ...opts, + }); + },
358-365: Fix listInvoices: collection endpoint should not accept identifierThis currently fetches a single invoice; adjust to call
/Invoices.- listInvoices({ - invoiceIdentifier, ...opts - }) { - return this._makeRequest({ - path: `/Invoices/${invoiceIdentifier}`, - ...opts, - }); - }, + listInvoices(opts = {}) { + return this._makeRequest({ + path: `/Invoices`, + ...opts, + }); + },
366-373: Fix listManualJournals: collection endpoint should not accept identifierThis currently retrieves a single manual journal; adjust to call
/ManualJournals.- listManualJournals({ - manualJournalId, ...opts - }) { - return this._makeRequest({ - path: `/ManualJournals/${manualJournalId}`, - ...opts, - }); - }, + listManualJournals(opts = {}) { + return this._makeRequest({ + path: `/ManualJournals`, + ...opts, + }); + },
🧹 Nitpick comments (2)
components/xero_accounting_api/xero_accounting_api.app.mjs (2)
99-116: Make_makeRequestexplicitly support absolute URLsRight now absolute URLs work by overriding via
...opts, which is implicit. Accept aurlparam explicitly and prefer it overpathto make intent clear and reduce confusion._makeRequest({ $ = this, tenantId, modifiedSince, path, headers, + url, ...opts }) { - return axios($, { - url: `${BASE_URL}/api.xro/2.0${path}`, + const finalUrl = url || `${BASE_URL}/api.xro/2.0${path}`; + return axios($, { + url: finalUrl, headers: this.getHeader({ tenantId, modifiedSince, headers, }), ...opts, }); },
194-202: Optional: Confirm headers for PDF download (if applicable)
downloadInvoicecurrently performs a GET on/Invoices/{id}identical togetInvoiceById. If the intent is to download a PDF, ensure callers passheaders: { Accept: "application/pdf" }and appropriateresponseType(e.g.,arraybuffer). Otherwise, consider consolidating withgetInvoiceById.
📜 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 selected for processing (1)
components/xero_accounting_api/xero_accounting_api.app.mjs(3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-29T22:59:38.825Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15436
File: components/printful/printful.app.mjs:55-63
Timestamp: 2025-01-29T22:59:38.825Z
Learning: Console.log statements should be removed before merging PRs to maintain code quality and prevent potential security risks from exposing sensitive information in logs.
Applied to files:
components/xero_accounting_api/xero_accounting_api.app.mjs
🧬 Code Graph Analysis (1)
components/xero_accounting_api/xero_accounting_api.app.mjs (2)
components/xero_accounting_api/common/constants.mjs (4)
DB_LAST_DATE_CHECK(1-1)DB_LAST_DATE_CHECK(1-1)BASE_URL(2-2)BASE_URL(2-2)components/xero_accounting_api/common/util.mjs (1)
chainQueryString(108-109)
⏰ 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). (3)
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
- GitHub Check: Lint Code Base
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.
LGTM!
…consistency. Key changes include: - Updated API request methods to use consistent casing for paths (e.g., `/Contacts` and `/Invoices`). - Enhanced error handling in actions to provide clearer feedback when no results are found. - Removed deprecated `find-contact` action and streamlined contact-related actions. - Bumped versions for several actions to reflect updates and improvements. These changes enhance the reliability and maintainability of the Xero Accounting API integration.
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: 13
♻️ Duplicate comments (14)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
18-21: ContactNumber is not supported by GET /Contacts/{id}; update prop description or add fallback in app client
The action routes to getContactById, which generally maps to GET /Contacts/{ContactID}. Xero does not natively support fetching a contact by ContactNumber at that endpoint. Either (a) clarify the prop to accept ContactID (GUID) only, or (b) add a fallback in the app to search by ContactNumber.- description: "Xero identifier of the contact to get. Possible values: \n* **ContactID** - The Xero identifier for a contact e.g. 297c2dc5-cc47-4afd-8ec8-74990b8761e9\n* **ContactNumber** - A custom identifier specified from another system e.g. a CRM system has a contact number of CUST100", + description: "Xero ContactID (GUID) of the contact to retrieve (e.g. 297c2dc5-cc47-4afd-8ec8-74990b8761e9).\nNote: Retrieval by ContactNumber is not supported by GET /Contacts/{id}. To fetch by ContactNumber, use the List Contacts action with an appropriate Where filter.",If you prefer the fallback behavior, I can propose a patch to components/xero_accounting_api/xero_accounting_api.app.mjs to attempt GET by ID first and, on 404 or non-GUID, list and filter by ContactNumber.
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
54-60: Pass tenantId to _makeRequest (required for xero-tenant-id header); parse queryString into params objectWithout tenantId, the app can’t set the xero-tenant-id header, and requests will likely fail. Also, axios params typically expects an object; parse the query string if provided.
- const response = await this.xeroAccountingApi._makeRequest({ - $, - method: this.requestMethod, - path: this.relativeUrl, - params: this.queryString, - data: parseObject(this.requestBody), - }); + const response = await this.xeroAccountingApi._makeRequest({ + $, + method: this.requestMethod, + path: this.relativeUrl, + tenantId: this.tenantId, + params: (typeof this.queryString === "string" && this.queryString.trim()) + ? Object.fromEntries(new URLSearchParams(this.queryString)) + : this.queryString, + data: parseObject(this.requestBody), + });components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (2)
149-154: Fix typos: puchasesDefaultAccountCode → purchasesDefaultAccountCodeSpelling errors in prop names degrade DX and ecosystem consistency.
- puchasesDefaultAccountCode: { + purchasesDefaultAccountCode: { label: "Purchases Default Account Code", type: "string", description: "The default purchases [account code](https://developer.xero.com/documentation/api/accounts) for contacts", optional: true, },- PurchasesDefaultAccountCode: this.puchasesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode,Also applies to: 241-241
155-166: sales/purchases tracking categories should accept arrays (parse JSON) and fix spelling of purchasesTrackingCategoriesXero expects arrays for SalesTrackingCategories and PurchasesTrackingCategories. Update types, parse inputs, and fix the “puechases” typo.
salesTrackingCategories: { label: "Sales Tracking Categories", - type: "string", - description: "The default sales [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", + type: "any", + description: "The default sales [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts. Accepts an array or a JSON string representing an array of tracking category assignments.", optional: true, }, - puechasesTrackingCategories: { + purchasesTrackingCategories: { label: "Purchases Tracking Categories", - type: "string", - description: "The default purchases [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", + type: "any", + description: "The default purchases [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts. Accepts an array or a JSON string representing an array of tracking category assignments.", optional: true, },- SalesTrackingCategories: this.salesTrackingCategories, - PurchasesTrackingCategories: this.puechasesTrackingCategories, + SalesTrackingCategories: parseObject(this.salesTrackingCategories), + PurchasesTrackingCategories: parseObject(this.purchasesTrackingCategories),Also applies to: 242-243
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (1)
146-147: Fix casing: LineItems key is misspelled (capital “I” required)Xero expects LineItems with a capital “I”. Using Lineitems will drop all line items from the request.
Apply this diff:
- Lineitems: this.lineItems, + LineItems: this.lineItems,components/xero_accounting_api/xero_accounting_api.app.mjs (6)
117-121: Use consistent URL construction patternFollow the template-literal pattern used elsewhere.
- return this._makeRequest({ - url: BASE_URL + "/connections", - }); + return this._makeRequest({ + url: `${BASE_URL}/connections`, + });
57-62: Avoid potential crash when no options exist for the tracking categoryThis assumes TrackingCategories[0].Options exists. It will throw if the category isn’t found or has no options.
Apply this diff:
- return trackingCategories[0].Options.map(({ - TrackingOptionID, Name, - }) => ({ - label: Name, - value: TrackingOptionID, - })); + const trackingCategory = trackingCategories?.[0]; + if (!trackingCategory?.Options?.length) return []; + return trackingCategory.Options.map(({ TrackingOptionID, Name }) => ({ + label: Name, + value: TrackingOptionID, + }));
168-178: Don’t pass boolean to axios params; preserve caller paramsWhen where is falsy, params becomes false. Also, this overwrites opts.params. Build params by merging.
- return this._makeRequest({ - path: "/Contacts", - params: where && { - Where: where, - }, - ...opts, - }); + const params = { + ...(opts.params || {}), + ...(where ? { Where: where } : {}), + }; + return this._makeRequest({ + path: "/Contacts", + ...opts, + params, + });
205-215: Same issue: boolean params and lost caller paramsMirror the fix from getContact().
- return this._makeRequest({ - path: "/Invoices", - ...opts, - params: where && { - Where: where, - }, - }); + const params = { + ...(opts.params || {}), + ...(where ? { Where: where } : {}), + }; + return this._makeRequest({ + path: "/Invoices", + ...opts, + params, + });
347-353: listInvoices fetches a single invoice (wrong endpoint/signature)This method should return the collection. Current implementation returns a single invoice by ID.
Apply this diff:
- listInvoices({ - invoiceIdentifier, ...opts - }) { - return this._makeRequest({ - path: `/Invoices/${invoiceIdentifier}`, - ...opts, - }); - }, + listInvoices(opts = {}) { + return this._makeRequest({ + path: "/Invoices", + ...opts, + }); + },
355-362: listManualJournals fetches a single manual journal (wrong endpoint/signature)This should call the collection endpoint.
- listManualJournals({ - manualJournalId, ...opts - }) { - return this._makeRequest({ - path: `/ManualJournals/${manualJournalId}`, - ...opts, - }); - }, + listManualJournals(opts = {}) { + return this._makeRequest({ + path: "/ManualJournals", + ...opts, + }); + },components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (3)
149-154: Fix prop key typo: puchasesDefaultAccountCode → purchasesDefaultAccountCodePublic prop name has a typo and the payload pulls from the misspelled key. Correct now to avoid long-term API friction.
- puchasesDefaultAccountCode: { + purchasesDefaultAccountCode: { label: "Purchases Default Account Code", type: "string", description: "The default purchases [account code](https://developer.xero.com/documentation/api/accounts) for contacts", optional: true, },- PurchasesDefaultAccountCode: this.puchasesDefaultAccountCode, + PurchasesDefaultAccountCode: this.purchasesDefaultAccountCode,Also applies to: 236-236
155-160: Sales tracking categories should accept JSON and be parsedXero expects arrays/objects. Type "string" without parsing likely produces invalid payloads.
- salesTrackingCategories: { + salesTrackingCategories: { label: "Sales Tracking Categories", - type: "string", + type: "any", description: "The default sales [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", optional: true, },- SalesTrackingCategories: this.salesTrackingCategories, + SalesTrackingCategories: parseObject(this.salesTrackingCategories),Also applies to: 237-237
161-166: Purchases tracking categories: same issue (parse and allow arrays/objects)Mirror the change above for purchases.
- puechasesTrackingCategories: { + purchasesTrackingCategories: { label: "Purchases Tracking Categories", - type: "string", + type: "any", description: "The default purchases [tracking categories](https://developer.xero.com/documentation/api/tracking-categories/) for contacts", optional: true, },- PurchasesTrackingCategories: this.puechasesTrackingCategories, + PurchasesTrackingCategories: parseObject(this.purchasesTrackingCategories),Also applies to: 238-238
🧹 Nitpick comments (32)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (2)
17-22: Broaden date format guidance for modifiedAfterXero uses the If-Modified-Since header semantics and supports full timestamps. Limiting the UI hint to YYYY-MM-DD is unnecessarily restrictive.
Apply this diff to improve the hint:
- description: "Filter by a date. Only contacts modified since this date will be returned. Format: YYYY-MM-DD", + description: "Return contacts modified since this date/time. Accepts ISO 8601 (e.g. 2025-01-01 or 2025-01-01T00:00:00Z).",
42-46: Use an integer type for PagePage is numeric per Xero docs. Using an integer improves validation and UX.
Apply this diff:
- type: "string", + type: "integer",components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (2)
4-8: Nit: tighten the description phrasingMinor copy tweak improves clarity and matches other actions’ tone.
Apply this diff:
- description: "Lists information from tracking categories [See the documentation](https://developer.xero.com/documentation/api/accounting/trackingcategories).", + description: "List tracking categories. See the documentation: https://developer.xero.com/documentation/api/accounting/trackingcategories",
9-17: Optional Enhancement: AddincludeArchivedFlagThe Xero wrapper’s
getTrackingCategories(opts = {})spreads all passed options (…opts) into its HTTP request, so a top‐levelparamsobject is supported. To expose archived categories:• Add an
includeArchivedboolean prop:props: { xeroAccountingApi, tenantId: { propDefinition: [xeroAccountingApi, "tenantId"], }, + includeArchived: { + type: "boolean", + label: "Include archived", + description: "Include archived tracking categories", + optional: true, + }, },• Pass it through the API call:
- const response = await this.xeroAccountingApi.getTrackingCategories({ - $, - tenantId: this.tenantId, - }); + const response = await this.xeroAccountingApi.getTrackingCategories({ + $, + tenantId: this.tenantId, + params: { includeArchived: this.includeArchived }, + });This addition is optional but follows common list-endpoint conventions. Let me know if you’d like any assistance integrating it.
components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (5)
19-24: Standardize prop casing: rename contactID → contactId to align with repo conventionsMost actions in this PR use camelCase IDs (invoiceId, itemId, contactId in other files). This prop stands out with PascalCase suffix and likely creates inconsistency for users.
Apply this diff within the prop block:
- contactID: { + contactId: { type: "string", - label: "Contact ID", + label: "Contact ID", description: "ID of the contact that requires update.", optional: true, },And update references in changed lines:
- if (!this.contactID && !this.name) { + if (!this.contactId && !this.name) {For lines outside the changed segment, also update:
- Line 73:
const { contactID, ... } = this;→const { contactId, ... } = this;- Line 90:
contactID && (data.ContactID = contactID);→contactId && (data.ContactID = contactId);
96-96: Make the success summary accurate for both create and update flowsThis message can mislead when an update occurs.
Apply this diff:
- response && $.export("$summary", "Contact created successfully"); + if (response) { + const action = this.contactId ? "updated" : "created"; + $.export("$summary", `Contact ${action} successfully`); + }
7-7: Trim trailing whitespace in the action nameMinor polish to avoid UI oddities.
- name: "Create or update contact ", + name: "Create or Update Contact",
34-34: Fix minor typos/punctuation in descriptionsSmall textual nits that improve professionalism.
- description: "First name of contact person .", + description: "First name of contact person.",- description: "User defined account number..", + description: "User-defined account number.",Also applies to: 52-52
69-71: Validation logic: consider allowing other Xero identifiers if supportedCurrently, only contactId or name passes validation. If the wrapper supports identifying contacts by fields like ContactNumber or EmailAddress for upsert semantics, consider relaxing this check accordingly.
Would you like me to adjust the validation to accept additional identifiers (e.g., emailAddress, accountNumber) if present?
components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (2)
55-55: Guard against missing response fields when summarizing countAvoids TypeError if CreditNotes is absent or undefined.
- $.export("$summary", `Successfully fetched ${response.CreditNotes.length} credit notes`); + $.export("$summary", `Successfully fetched ${response?.CreditNotes?.length ?? 0} credit notes`);
57-60: Don’t swallow all errors; only treat “not found/empty” as non-fatalReturning {} on any exception makes debugging operational issues harder. Consider narrowing the catch to known empty/not-found cases or rethrowing unexpected errors.
- } catch (e) { - $.export("$summary", "No credit notes found"); - return {}; - } + } catch (e) { + const status = e?.response?.status; + if (status === 404) { + $.export("$summary", "No credit notes found"); + return {}; + } + throw e; + }components/xero_accounting_api/actions/upload-file/upload-file.mjs (3)
78-78: Avoid unnecessary Buffer copyfileBinary is already a Buffer. Re-wrapping creates an extra allocation without benefit.
- data: Buffer.from(fileBinary, "binary"), + data: fileBinary,
73-77: Set a safe default Content-TypeSome sources may not provide a MIME type; default to application/octet-stream.
- "Content-Type": metadata.contentType, + "Content-Type": metadata.contentType || "application/octet-stream",
51-60: Potential memory usage concern for large filesConverting the entire stream to a Buffer can be memory-heavy for large attachments. If the app wrapper supports streams, prefer passing the Readable stream directly to avoid buffering.
I can update this action to pass the stream through (and adjust the wrapper if needed). Want me to draft that change?
components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
33-36: Avoid masking unexpected errorsCatching all errors and returning {} hampers observability. Limit to 404 (not found) and rethrow others.
- } catch (e) { - $.export("$summary", `No invoice found with identifier: ${this.invoiceId}`); - return {}; - } + } catch (e) { + if (e?.response?.status === 404) { + $.export("$summary", `No invoice found with identifier: ${this.invoiceId}`); + return {}; + } + throw e; + }components/xero_accounting_api/actions/get-item/get-item.mjs (1)
33-36: Same error handling refinement as get-invoiceOnly treat “not found” as a benign case; rethrow other errors.
- } catch (e) { - $.export("$summary", `No item found with identifier: ${this.itemId}`); - return {}; - } + } catch (e) { + if (e?.response?.status === 404) { + $.export("$summary", `No item found with identifier: ${this.itemId}`); + return {}; + } + throw e; + }components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
33-36: Differentiate 404 “not found” from other errorsCurrently all errors are summarized as “No invoice found…”, which can mask auth/network issues. Recommend special-casing 404 and rethrowing others.
- } catch (e) { - $.export("$summary", `No invoice found with identifier: ${this.invoiceId}`); - return {}; - } + } catch (e) { + if (e?.response?.status === 404) { + $.export("$summary", `No invoice found with identifier: ${this.invoiceId}`); + return {}; + } + throw e; + }components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
33-36: Refine error handling to avoid masking non-404 errorsMirror the pattern of surfacing “not found” only on 404, and rethrow other errors for visibility.
- } catch (e) { - $.export("$summary", `No contact found with identifier: ${this.contactIdentifier}`); - return {}; - } + } catch (e) { + if (e?.response?.status === 404) { + $.export("$summary", `No contact found with identifier: ${this.contactIdentifier}`); + return {}; + } + throw e; + }components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (2)
90-91: Guard against undefined response shape when building summaryIf the app returns a response without Invoices, accessing length will throw. Use optional chaining and provide a robust count.
- $.export("$summary", `Successfully fetched ${response.Invoices.length} invoices`); + const count = response?.Invoices?.length ?? 0; + $.export("$summary", `Successfully fetched ${count} invoice${count === 1 ? "" : "s"}`);
24-27: Nit: fix wording to “Invoice IDs”Minor doc cleanup.
- description: "Filter by a comma-separated list of InvoicesIDs. See [details](https://developer.xero.com/documentation/api/invoices#optimised-queryparameters).", + description: "Filter by a comma-separated list of Invoice IDs. See [details](https://developer.xero.com/documentation/api/invoices#optimised-queryparameters).",components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (2)
151-152: Guard summary against missing response fieldsIf the API returns an unexpected shape (errors, empty array), accessing BankTransactions[0] will throw.
Apply this diff:
- $.export("$summary", `Successfully created bank transaction with ID: ${response.BankTransactions[0].BankTransactionID}`); + const id = response?.BankTransactions?.[0]?.BankTransactionID || "unknown"; + $.export("$summary", `Successfully created bank transaction with ID: ${id}`);
24-29: Nit: description says “Bank Account transaction” but should be “Bank Account”Minor wording fix to avoid confusion.
- description: "The ID of the Bank Account transaction. If AccountID is not included then Code is required.", + description: "The ID of the Bank Account. If AccountID is not included then Code is required.",components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (2)
101-106: Consistency: accountsPayableTaxType namingProp is named accountPayableType but maps to AccountsPayableTaxType. Rename for clarity and consistency with accountReceivableTaxType.
- accountPayableType: { + accountsPayableTaxType: { label: "Account Payable Type", type: "string", description: "Store certain address types for a contact - see address types", optional: true, },- AccountsPayableTaxType: this.accountPayableType, + AccountsPayableTaxType: this.accountsPayableTaxType,Also consider updating the description to match Receivable’s (“Default tax type used for contact on AP invoices”).
Also applies to: 228-228
250-251: Summary should use the ID returned by the API, not the input contactIdWhen creating a new contact, this.contactId may be empty. Use the response to populate the summary.
- $.export("$summary", `Successfully created or updated contact with ID: ${this.contactId}`); + const id = response?.Contacts?.[0]?.ContactID || this.contactId || "unknown"; + $.export("$summary", `Successfully created or updated contact with ID: ${id}`);components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (4)
17-22: Improve Modified After UX hint (explicit ISO 8601 with Z and placeholder)Minor clarity tweak so users provide a proper UTC timestamp including the Z suffix.
Apply:
label: "Modified After", type: "string", - description: "The ModifiedAfter filter is actually an HTTP header: **'If-Modified-Since'**. A UTC timestamp (yyyy-mm-ddThh:mm:ss) . Only manual journals created or modified since this timestamp will be returned e.g. 2009-11-12T00:00:00", + description: "The ModifiedAfter filter maps to the 'If-Modified-Since' HTTP header. Provide a UTC timestamp in ISO 8601 format (e.g., 2009-11-12T00:00:00Z). Only manual journals created or modified since this timestamp will be returned.", + placeholder: "2009-11-12T00:00:00Z", optional: true,
23-28: Fix small grammar nit in Where descriptionReplace “an any” with “any”.
type: "string", - description: "Filter by an any element (*see [Filters](https://developer.xero.com/documentation/api/requests-and-responses#get-modified)*)", + description: "Filter by any element (*see [Filters](https://developer.xero.com/documentation/api/requests-and-responses#get-modified)*)", optional: true,
35-40: Page should be an integer (enforce numeric input and avoid coercion)Using an integer type improves UX and prevents string-to-number conversion bugs. Add a minimum bound.
label: "Page", - type: "string", + type: "integer", + min: 1, description: "Up to 100 manual journals will be returned per call, with journal lines shown for each, when the page parameter is used e.g. page=1", optional: true,
55-56: Guard summary against missing/undefined ManualJournalsAvoids a TypeError when the response has no ManualJournals array.
- $.export("$summary", `Successfully fetched ${response.ManualJournals.length} manual journals`); - return response; + const count = Array.isArray(response?.ManualJournals) ? response.ManualJournals.length : 0; + $.export("$summary", `Successfully fetched ${count} manual journals`); + return response;components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs (4)
22-27: Nit: clean up minor copy/punctuation for “name” propTighten the description to remove trailing space and improve readability.
- description: "Full name of contact/organization ", + description: "Full name of the contact or organization.",
31-33: Nit: align wording for “emailAddress” propSmall copy tweak for consistency and clarity.
- description: "Email address of contact/organization.", + description: "Email address of the contact or organization.",
35-41: Nit: improve toggle copy and provide a defaultAdd a default of “No” and remove the stray punctuation in the description. This keeps behavior explicit when users don’t change the control.
- description: "Create a new contact if not found?.", + description: "Create a new contact if not found?", label: "Create a new contact if not found", type: "string", options: [ "Yes", "No", ], + default: "No",
47-72: Nit: minor grammar/punctuation in additional propsTidy up descriptions for first/last name; current strings include an extra space and could be slightly clearer.
props.firstName = { type: "string", label: "First name", - description: "First name of contact person .", + description: "First name of the contact person.", optional: true, }; props.lastName = { type: "string", label: "Last name", - description: "Last name of contact person.", + description: "Last name of the contact person.", optional: true, };
📜 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 selected for processing (21)
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs(3 hunks)components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs(1 hunks)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs(4 hunks)components/xero_accounting_api/actions/download-invoice/download-invoice.mjs(2 hunks)components/xero_accounting_api/actions/find-contact/find-contact.mjs(0 hunks)components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs(3 hunks)components/xero_accounting_api/actions/get-contact/get-contact.mjs(1 hunks)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs(1 hunks)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs(1 hunks)components/xero_accounting_api/actions/get-item/get-item.mjs(1 hunks)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs(1 hunks)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs(1 hunks)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs(1 hunks)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs(1 hunks)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs(1 hunks)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs(1 hunks)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs(2 hunks)components/xero_accounting_api/actions/upload-file/upload-file.mjs(2 hunks)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs(2 hunks)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs(2 hunks)components/xero_accounting_api/xero_accounting_api.app.mjs(3 hunks)
💤 Files with no reviewable changes (1)
- components/xero_accounting_api/actions/find-contact/find-contact.mjs
🚧 Files skipped from review as they are similar to previous changes (2)
- components/xero_accounting_api/actions/download-invoice/download-invoice.mjs
- components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
PR: PipedreamHQ/pipedream#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/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjscomponents/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs
📚 Learning: 2024-10-08T16:42:59.225Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14229
File: components/americommerce/actions/update-customer/update-customer.mjs:89-94
Timestamp: 2024-10-08T16:42:59.225Z
Learning: When defining boolean properties in AmeriCommerce components (e.g., in `update-customer.mjs`), ensure that the label and description are consistent and clearly indicate the intent, especially when using negations like "No Account", to avoid confusion.
Applied to files:
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs
📚 Learning: 2025-01-29T22:59:38.825Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15436
File: components/printful/printful.app.mjs:55-63
Timestamp: 2025-01-29T22:59:38.825Z
Learning: Console.log statements should be removed before merging PRs to maintain code quality and prevent potential security risks from exposing sensitive information in logs.
Applied to files:
components/xero_accounting_api/xero_accounting_api.app.mjs
🧬 Code Graph Analysis (18)
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (13)
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (1)
response(126-149)components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
response(67-79)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (11)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-60)components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
response(67-79)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)
components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (5)
components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/google_drive/actions/create-file-from-template/create-file-from-template.mjs (1)
e(77-79)
components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (5)
components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (8)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)
components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (8)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-60)
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (10)
components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (7)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/upload-file/upload-file.mjs (3)
components/tinypng/actions/compress-image/compress-image.mjs (1)
getFileStreamAndMetadata(26-28)components/signnow/actions/upload-document-with-tags/upload-document-with-tags.mjs (1)
getFileStreamAndMetadata(46-48)components/zip_archive_api/actions/compress-files/compress-files.mjs (1)
getFileStreamAndMetadata(53-55)
components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (5)
components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-60)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (5)
components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)
components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)
components/xero_accounting_api/xero_accounting_api.app.mjs (3)
components/xero_accounting_api/common/constants.mjs (4)
DB_LAST_DATE_CHECK(1-1)DB_LAST_DATE_CHECK(1-1)BASE_URL(2-2)BASE_URL(2-2)components/xero_accounting_api/sources/new-updated-invoice/new-updated-invoice.mjs (1)
invoices(38-43)components/xero_accounting_api/common/util.mjs (1)
chainQueryString(108-109)
components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (4)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)
components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (4)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (14)
components/xero_accounting_api/actions/create-tracking-category/create-tracking-category.mjs (1)
response(33-39)components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-item/get-item.mjs (1)
response(25-29)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (1)
response(20-23)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-60)components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
response(67-79)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)
components/xero_accounting_api/actions/get-item/get-item.mjs (9)
components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)components/xero_accounting_api/actions/create-update-contact/create-update-contact.mjs (1)
response(91-95)components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (1)
response(29-33)components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
response(25-29)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-60)components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
response(67-79)components/xero_accounting_api/actions/xero-accounting-create-or-update-contact/xero-accounting-create-or-update-contact.mjs (1)
response(211-248)components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
response(215-253)
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs (1)
components/xero_accounting_api/common/util.mjs (2)
removeNullEntries(3-20)formatQueryString(65-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: pnpm publish
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
🔇 Additional comments (23)
components/xero_accounting_api/actions/get-tracking-category/get-tracking-category.mjs (4)
1-1: Import path and app reference look correct.The relative path resolves to the app module and the default import naming is consistent with other actions.
10-26: Props wiring LGTM.
- Uses shared propDefinitions for tenantId and trackingCategoryId.
- Correctly scopes trackingCategoryId options to the selected tenantId.
35-36: Success summary is clear.Returning the API response and exporting a concise $summary is consistent with other actions.
27-33: No changes needed—method name is correct
The Xero client defines and usesgetTrackingCategory(seecomponents/xero_accounting_api/xero_accounting_api.app.mjs), and there is nogetTrackingCategoryByIdmethod. Your existing call is consistent with the client API.components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (3)
7-7: Confirm version bump reflects breaking prop changesThis action’s public props changed (tenantId via propDefinition, removed legacy props). If users’ workflows might break, consider a breaking version bump consistent with your repo’s conventions for Pipedream components.
What’s the expected semver policy here for components under 0.x? If breaking, consider 0.3.0 (or 1.0.0 if you’ve graduated the app).
10-16: Good move to app-based propDefinition for tenantIdSwitching to the centralized app and pulling tenantId via propDefinition aligns with the rest of the PR and reduces duplication.
1-1: Import path is correct; no change required
Verified thatcomponents/xero_accounting_api/xero_accounting_api.app.mjsis reached byimport xeroAccountingApi from "../../xero_accounting_api.app.mjs";inactions/list-contacts/list-contacts.mjs. This pattern matches all other actions and the app exports (e.g.,listContacts). No updates needed.Likely an incorrect or invalid review comment.
components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs (3)
1-1: Import path and app binding look correctThe relative path to the app module is correct from this file’s location, and importing the default export aligns with other actions’ patterns.
9-17: Props wiring LGTMUsing the app and the tenantId propDefinition is consistent with the rest of the Xero actions.
20-23: Confirmed getTrackingCategories exists and returns TrackingCategories
I verified that:
getTrackingCategoriesis implemented in components/xero_accounting_api/xero_accounting_api.app.mjs (lines 269–272).- Its response object includes a
TrackingCategoriesarray (destructured at line 32), matching how it’s used in list-tracking-categories.components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
1-16: Migration to app wrapper looks goodProps, tenantId propDefinition, and wrapper usage align with the broader PR pattern.
components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
1-50: Overall migration to wrapper is cleanThe action cleanly delegates auth and endpoint handling to the app wrapper and surfaces a clear summary.
components/xero_accounting_api/actions/get-invoice/get-invoice.mjs (1)
1-31: Wrapper migration and prop wiring LGTMConsistent with other actions: tenantId via propDefinition, camelCase props, and concise success summary.
components/xero_accounting_api/actions/get-item/get-item.mjs (1)
1-31: Action structure and wrapper usage look goodMatches the PR-wide pattern; clear inputs and summaries.
components/xero_accounting_api/actions/get-invoice-online-url/get-invoice-online-url.mjs (1)
24-33: LGTM: migrated to app client and standardized props/flowThe action correctly delegates to the app method, uses propDefinition for tenantId, and exports a clear success summary. This aligns with the broader refactor pattern.
components/xero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs (1)
210-213: Validation is goodGuarding against missing tenantId/contactId with ConfigurationError is appropriate and matches adjacent actions.
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs (1)
118-124: Validation is goodRequiring either Bank Account Code or ID, and either Contact ID or Name, via ConfigurationError is solid.
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (4)
1-1: Switched to xeroAccountingApi app wrapper import — LGTMImport path matches the new app wrapper used across related actions in this PR.
10-16: PropDefinition for tenantId via app wrapper — LGTMConsistent with other migrated actions in the PR; reduces duplication and centralizes validation.
7-7: No lingering old prop references inlist-manual-journalsaction
Ranrg -n -C2 -P '\btenant_id\b|\bmodified_after\b' components/xero_accounting_api/actions/list-manual-journals/— no matches found. Proceed with version bump to 0.2.0, but please:
• Update release notes to call out the prop renames (
tenant_id→tenantId,modified_after→modifiedAfter).
• Verify that existing workflows are pinned to the prior version to avoid unintended breaks.
43-53: ✅ VerifiedlistManualJournalswrapper signature and parameter casingI’ve confirmed in
components/xero_accounting_api/xero_accounting_api.app.mjs(lines 355–362) that:
listManualJournalsis defined with({ manualJournalId, ...opts })- It forwards
...opts—including yourparamsobject withWhere,order, andpage—directly to_makeRequest- The call site in
actions/list-manual-journals/list-manual-journals.mjsmirrors the existinglistInvoicespatternNo further changes are needed here.
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs (2)
11-12: Description and version bump look goodClearer description with docs link and a semantic version bump to 0.1.0. No issues here.
92-108: getContact filter formatting verified
getContactexpects a singleWhereparameter containing a preformatted Xero filter string.formatQueryString(payload, true)URL-encodes each key/value pair and wraps values in double quotes;chainQueryStringthen replaces&withANDto form a valid Xero “where” expression.- When only
NameorEmailAddressis provided, you get a single-condition filter; if both are supplied, they’re combined with AND. Change to OR semantics only if that’s your intent.No further changes needed.
components/xero_accounting_api/actions/create-bank-transaction/create-bank-transaction.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/find-or-create-contact/find-or-create-contact.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/list-tracking-categories/list-tracking-categories.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs
Show resolved
Hide resolved
...ero_accounting_api/actions/xero-accounting-update-contact/xero-accounting-update-contact.mjs
Show resolved
Hide resolved
… changes include: - Updated `listInvoices`, `listManualJournals`, `listCreditNotes`, and `listContacts` methods to use `modifiedSince` instead of `modifiedAfter` for parameter naming consistency. - Simplified API request paths for `listInvoices` and `listManualJournals` by removing unnecessary identifiers. These modifications enhance the clarity and maintainability of the API integration.
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
♻️ Duplicate comments (5)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
55-74: Don’t swallow API errors; set summary based on result count and filter out undefined paramsLet errors bubble so users see real failures. Also guard against undefined/empty param values and handle missing Contacts safely when computing the count.
- async run({ $ }) { - try { - const response = await this.xeroAccountingApi.listContacts({ - $, - tenantId: this.tenantId, - modifiedSince: this.modifiedAfter, - params: { - IDs: this.ids, - Where: this.where, - order: this.order, - page: this.page, - includeArchived: this.includeArchived, - }, - }); - - $.export("$summary", `Successfully fetched ${response.Contacts.length} contacts`); - return response; - } catch (e) { - $.export("$summary", "No contacts found"); - return {}; - } - }, + async run({ $ }) { + const response = await this.xeroAccountingApi.listContacts({ + $, + tenantId: this.tenantId, + modifiedSince: this.modifiedAfter, + params: Object.fromEntries(Object.entries({ + IDs: this.ids, + Where: this.where, + order: this.order, + page: this.page, + includeArchived: this.includeArchived, + }).filter(([, v]) => v !== undefined && v !== "")), + }); + + const count = response?.Contacts?.length ?? 0; + $.export("$summary", count ? `Successfully fetched ${count} contacts` : "No contacts found"); + return response; + },components/xero_accounting_api/xero_accounting_api.app.mjs (4)
118-120: Prefer template literals for URL consistencyAligns with the established
${BASE_URL}/...pattern.return this._makeRequest({ - url: BASE_URL + "/connections", + url: `${BASE_URL}/connections`, });
57-63: Guard against missing tracking category/options before mappingAvoid potential null/undefined errors when no categories or options exist.
- return trackingCategories[0].Options.map(({ - TrackingOptionID, Name, - }) => ({ - label: Name, - value: TrackingOptionID, - })); + const trackingCategory = trackingCategories?.[0]; + if (!trackingCategory?.Options?.length) { + return []; + } + return trackingCategory.Options.map(({ + TrackingOptionID, Name, + }) => ({ + label: Name, + value: TrackingOptionID, + }));
172-178: Avoid boolean params and preserve caller-provided params in getContactPassing
where && { ... }can set params tofalse. Also merge with any existingopts.params.- return this._makeRequest({ - path: "/Contacts", - params: where && { - Where: where, - }, - ...opts, - }); + const params = { + ...(opts.params || {}), + ...(where ? { Where: where } : {}), + }; + return this._makeRequest({ + path: "/Contacts", + ...opts, + params, + });
209-215: Avoid boolean params and preserve caller-provided params in getInvoiceSame pattern as getContact: never pass a boolean as params and merge with existing params.
- return this._makeRequest({ - path: "/Invoices", - ...opts, - params: where && { - Where: where, - }, - }); + const params = { + ...(opts.params || {}), + ...(where ? { Where: where } : {}), + }; + return this._makeRequest({ + path: "/Invoices", + ...opts, + params, + });
🧹 Nitpick comments (6)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
17-21: Clarify Modified After format to match Xero’s If-Modified-Since headerAlign with other actions and the API’s expected timestamp format to avoid confusion.
modifiedAfter: { label: "Modified After", - description: "Filter by a date. Only contacts modified since this date will be returned. Format: YYYY-MM-DD", + description: "UTC timestamp used for the If-Modified-Since header. Only contacts created or modified since this timestamp will be returned (e.g. 2009-11-12T00:00:00).", type: "string", optional: true, },components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (1)
17-22: Fix grammar and align description with If-Modified-Since formatMinor wording fix and consistent timestamp guidance.
modifiedAfter: { label: "Modified After", type: "string", - description: "The ModifiedAfter filter is actually an HTTP header: **'If-Modified-Since'.**\nA UTC timestamp (yyyy-mm-ddThh:mm:ss). Only credit notes or modified since this timestamp will be returned e.g. 2009-11-12T00:00:00", + description: "The ModifiedAfter filter is the HTTP header: **If-Modified-Since**.\nA UTC timestamp (yyyy-mm-ddThh:mm:ss). Only credit notes created or modified since this timestamp will be returned (e.g. 2009-11-12T00:00:00).", optional: true, },components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (2)
8-9: Typo and clarity: “aribitrary” → “arbitrary”; add “HTTP” and article- description: "Makes an aribitrary call to Xero Accounting API.", + description: "Makes an arbitrary HTTP call to the Xero Accounting API.",
20-23: Capitalize HTTP in user-facing textlabel: "Request Method", type: "string", - description: "Http method to use in the request.", + description: "HTTP method to use in the request.",components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
26-27: Typo in description: “InvoicesIDs” → “InvoiceIDs”- description: "Filter by a comma-separated list of InvoicesIDs. See [details](https://developer.xero.com/documentation/api/invoices#optimised-queryparameters).", + description: "Filter by a comma-separated list of InvoiceIDs. See [details](https://developer.xero.com/documentation/api/invoices#optimised-queryparameters).",components/xero_accounting_api/xero_accounting_api.app.mjs (1)
91-97: Prevent accidental override of Authorization headerUser-supplied headers can currently overwrite Authorization. Consider making Authorization authoritative while still allowing custom headers.
- const header = { - "Authorization": `Bearer ${this.$auth.oauth_access_token}`, - ...headers, - }; + const header = { + ...headers, + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + };Note: xero-tenant-id and If-Modified-Since are already set after this spread, so they remain authoritative.
📜 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 selected for processing (6)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs(1 hunks)components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs(1 hunks)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs(1 hunks)components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs(1 hunks)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs(2 hunks)components/xero_accounting_api/xero_accounting_api.app.mjs(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-01-29T22:59:38.825Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15436
File: components/printful/printful.app.mjs:55-63
Timestamp: 2025-01-29T22:59:38.825Z
Learning: Console.log statements should be removed before merging PRs to maintain code quality and prevent potential security risks from exposing sensitive information in logs.
Applied to files:
components/xero_accounting_api/xero_accounting_api.app.mjs
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
PR: PipedreamHQ/pipedream#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/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs
🧬 Code Graph Analysis (5)
components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs (5)
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-61)components/xero_accounting_api/actions/upload-file/upload-file.mjs (1)
response(67-79)
components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (3)
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (1)
response(56-67)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-61)
components/xero_accounting_api/xero_accounting_api.app.mjs (3)
components/xero_accounting_api/common/constants.mjs (4)
DB_LAST_DATE_CHECK(1-1)DB_LAST_DATE_CHECK(1-1)BASE_URL(2-2)BASE_URL(2-2)components/xero_accounting_api/sources/new-updated-invoice/new-updated-invoice.mjs (1)
invoices(38-43)components/xero_accounting_api/common/util.mjs (1)
chainQueryString(108-109)
components/xero_accounting_api/actions/list-contacts/list-contacts.mjs (4)
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/actions/list-invoices/list-invoices.mjs (1)
response(74-88)components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (1)
response(54-61)components/xero_accounting_api/actions/get-contact/get-contact.mjs (1)
response(25-29)
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs (2)
components/xero_accounting_api/actions/list-manual-journals/list-manual-journals.mjs (1)
response(44-53)components/xero_accounting_api/common/util.mjs (1)
parseObject(111-134)
⏰ 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
components/xero_accounting_api/actions/list-credit-notes/list-credit-notes.mjs
Show resolved
Hide resolved
components/xero_accounting_api/actions/list-invoices/list-invoices.mjs
Outdated
Show resolved
Hide resolved
components/xero_accounting_api/actions/make-an-api-call/make-an-api-call.mjs
Show resolved
Hide resolved
…ices.mjs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
/approve |
Resolves #17984
Summary by CodeRabbit
New Features
Improvements
Changes