Skip to content

Conversation

@jcortes
Copy link
Collaborator

@jcortes jcortes commented Dec 3, 2025

WHY

Resolves #7478

Summary by CodeRabbit

  • New Features

    • Create, retrieve, update, and delete invoices and sales orders in NetSuite
    • List and search invoices and sales orders with streaming pagination
    • Dynamic selection fields for customers, subsidiaries, invoices, and sales orders
    • Built-in JSON parsing for item/additional fields and configurable validation/replacement options
  • Chores

    • NetSuite component version bumped to 0.1.0

✏️ Tip: You can customize this high-level summary in your review settings.

@jcortes jcortes self-assigned this Dec 3, 2025
@vercel
Copy link

vercel bot commented Dec 3, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Dec 3, 2025 10:38pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Dec 3, 2025 10:38pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

Adds a full NetSuite integration: app-level REST client and CRUD helpers for invoices and sales orders, ten new action modules (create/get/list/update/delete), utilities for safe JSON parsing, validation constants, pagination support, and expanded propDefinitions for dynamic UI selection.

Changes

Cohort / File(s) Summary
Action Modules - Invoice Operations
components/netsuite/actions/create-invoice/create-invoice.mjs, components/netsuite/actions/delete-invoice/delete-invoice.mjs, components/netsuite/actions/get-invoice/get-invoice.mjs, components/netsuite/actions/list-invoices/list-invoices.mjs, components/netsuite/actions/update-invoice/update-invoice.mjs
New action definitions for invoice CRUD and listing. Create/update build JSON payloads (conditionally include subsidiary, items, additionalFields), set property validation headers, support replace semantics; get/delete use invoiceId; list paginates via app.paginate and supports search query/maxResults.
Action Modules - Sales Order Operations
components/netsuite/actions/create-sales-order/create-sales-order.mjs, components/netsuite/actions/delete-sales-order/delete-sales-order.mjs, components/netsuite/actions/get-sales-order/get-sales-order.mjs, components/netsuite/actions/list-sales-orders/list-sales-orders.mjs, components/netsuite/actions/update-sales-order/update-sales-order.mjs
New action definitions for sales order CRUD and listing. Create/update assemble request bodies with optional fields and JSON-parsed items/additionalFields, include validation headers and replace options; get/delete use salesOrderId; list uses pagination with optional query and maxResults.
App Module
components/netsuite/netsuite.app.mjs
Adds REST client helpers (getUrl, _headers, _makeRequest), CRUD methods for invoices and sales orders (list/get/create/update/delete), listSubsidiaries/listCustomers, an async paginate generator, and extensive propDefinitions (salesOrderId, invoiceId, subsidiaryId, customerId, searchQuery, items, validation options, replace, etc.).
Common Utilities & Constants
components/netsuite/common/utils.mjs, components/netsuite/common/constants.mjs
Adds parseJson(input, maxDepth) utility to safely parse JSON-like strings with depth and circular-reference protection; adds VALIDATION_OPTIONS constants: ERROR, WARNING, IGNORE.
Package Metadata
components/netsuite/package.json
Bumps package version from 0.0.1 to 0.1.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

  • Review focus areas:
    • components/netsuite/netsuite.app.mjs: REST request construction, auth/header handling, pagination generator correctness, and async prop option implementations.
    • Action modules: correct prop wiring, conditional payload assembly, consistent use of utils.parseJson, and header/query param usage for replace/validation.
    • components/netsuite/common/utils.mjs: parseJson recursion, maxDepth and circular reference handling.
    • Cross-file consistency for naming/field shapes between app methods and actions.

Suggested reviewers

  • lcaresia
  • GTFalcao

Pre-merge checks and finishing touches

❌ Failed checks (2 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title '[ACTIONS] Netsuite - new components' is vague and uses overly generic phrasing; it lacks specificity about what was actually implemented. Provide a more specific title that clearly describes the main additions, e.g., 'Add Netsuite CRUD actions for invoices and sales orders' or 'Implement Netsuite REST API integration with action modules'.
Description check ❓ Inconclusive The pull request description only includes 'Resolves #7478' without explaining the changes or implementation details required by the repository's template. Expand the description to fill the WHY section with context about why these Netsuite components are needed and what problem they solve for users.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements comprehensive Netsuite integration with CRUD actions and REST API support, satisfying the primary objective to add Netsuite application support as specified in issue #7478.
Out of Scope Changes check ✅ Passed All changes directly support the Netsuite integration objective: action modules for invoices and sales orders, app configuration, utilities for JSON parsing, and version bump are all within scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch netsuite-new-components

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jcortes jcortes force-pushed the netsuite-new-components branch from 80e4f15 to a4e6ce2 Compare December 3, 2025 22:38
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/netsuite/package.json (1)

3-15: Add trailing newline to fix eslint eol-last failure

Version bump to 0.1.0 looks appropriate, and the minimal manifest avoids unnecessary dependencies (consistent with not adding Node built-ins as deps, based on learnings). The remaining issue is the eslint error about a missing newline at end of file.

Add a trailing newline after the closing brace to satisfy eol-last and unblock the checks:

-  }
-}
+  }
+}
+
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6512c92 and a4e6ce2.

📒 Files selected for processing (14)
  • components/netsuite/actions/create-invoice/create-invoice.mjs (1 hunks)
  • components/netsuite/actions/create-sales-order/create-sales-order.mjs (1 hunks)
  • components/netsuite/actions/delete-invoice/delete-invoice.mjs (1 hunks)
  • components/netsuite/actions/delete-sales-order/delete-sales-order.mjs (1 hunks)
  • components/netsuite/actions/get-invoice/get-invoice.mjs (1 hunks)
  • components/netsuite/actions/get-sales-order/get-sales-order.mjs (1 hunks)
  • components/netsuite/actions/list-invoices/list-invoices.mjs (1 hunks)
  • components/netsuite/actions/list-sales-orders/list-sales-orders.mjs (1 hunks)
  • components/netsuite/actions/update-invoice/update-invoice.mjs (1 hunks)
  • components/netsuite/actions/update-sales-order/update-sales-order.mjs (1 hunks)
  • components/netsuite/common/constants.mjs (1 hunks)
  • components/netsuite/common/utils.mjs (1 hunks)
  • components/netsuite/netsuite.app.mjs (1 hunks)
  • components/netsuite/package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
Repo: PipedreamHQ/pipedream PR: 14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".

Applied to files:

  • components/netsuite/actions/create-sales-order/create-sales-order.mjs
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.

Applied to files:

  • components/netsuite/netsuite.app.mjs
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
Repo: PipedreamHQ/pipedream PR: 16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: The Salesloft API list endpoints (listPeople, listCadences, listUsers, listAccounts) return arrays directly in the response body, not wrapped in a metadata object with a nested data property. The _makeRequest method correctly returns response.data which contains the arrays that can be mapped over directly in propDefinitions.

Applied to files:

  • components/netsuite/netsuite.app.mjs
📚 Learning: 2024-12-12T19:23:09.039Z
Learnt from: jcortes
Repo: PipedreamHQ/pipedream PR: 14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.

Applied to files:

  • components/netsuite/package.json
🧬 Code graph analysis (5)
components/netsuite/actions/list-sales-orders/list-sales-orders.mjs (2)
components/netsuite/actions/list-invoices/list-invoices.mjs (2)
  • items (40-40)
  • paginator (41-50)
components/netsuite/netsuite.app.mjs (1)
  • items (303-303)
components/netsuite/actions/get-invoice/get-invoice.mjs (8)
components/netsuite/actions/create-invoice/create-invoice.mjs (1)
  • response (119-147)
components/netsuite/actions/create-sales-order/create-sales-order.mjs (1)
  • response (95-123)
components/netsuite/actions/delete-invoice/delete-invoice.mjs (1)
  • response (30-33)
components/netsuite/actions/delete-sales-order/delete-sales-order.mjs (1)
  • response (30-33)
components/netsuite/actions/get-sales-order/get-sales-order.mjs (1)
  • response (51-59)
components/netsuite/actions/update-invoice/update-invoice.mjs (1)
  • response (135-167)
components/netsuite/actions/update-sales-order/update-sales-order.mjs (1)
  • response (110-142)
components/netsuite/netsuite.app.mjs (1)
  • response (294-301)
components/netsuite/actions/update-sales-order/update-sales-order.mjs (3)
components/netsuite/actions/create-sales-order/create-sales-order.mjs (1)
  • response (95-123)
components/netsuite/actions/update-invoice/update-invoice.mjs (1)
  • response (135-167)
components/netsuite/netsuite.app.mjs (2)
  • response (294-301)
  • items (303-303)
components/netsuite/actions/delete-sales-order/delete-sales-order.mjs (1)
components/netsuite/actions/delete-invoice/delete-invoice.mjs (1)
  • response (30-33)
components/netsuite/actions/create-invoice/create-invoice.mjs (4)
components/netsuite/actions/create-sales-order/create-sales-order.mjs (1)
  • response (95-123)
components/netsuite/actions/update-invoice/update-invoice.mjs (1)
  • response (135-167)
components/netsuite/actions/update-sales-order/update-sales-order.mjs (1)
  • response (110-142)
components/netsuite/netsuite.app.mjs (2)
  • response (294-301)
  • items (303-303)
🪛 GitHub Actions: Pull Request Checks
components/netsuite/package.json

[error] 15-15: eslint: Newline required at end of file but not found. (eol-last) during 'pnpm exec eslint ...'

⏰ 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). (1)
  • GitHub Check: pnpm publish
🔇 Additional comments (8)
components/netsuite/common/constants.mjs (1)

1-7: Validation constants look good

The VALIDATION_OPTIONS map is clear and aligns well with how the actions configure validation behavior. No changes needed here.

components/netsuite/actions/delete-sales-order/delete-sales-order.mjs (1)

1-37: Delete Sales Order action is consistent and straightforward

The action wiring (props, annotations, and run implementation) is consistent with the existing delete-invoice pattern and correctly delegates to app.deleteSalesOrder, emitting a clear summary.

No issues from a correctness or API-shape standpoint.

components/netsuite/actions/get-invoice/get-invoice.mjs (1)

1-64: Get Invoice action matches established pattern

Props, annotations, and the run delegation to app.getInvoice (including optional params and summary) are consistent with the corresponding get-sales-order action and look correct.

No changes needed here.

components/netsuite/actions/update-invoice/update-invoice.mjs (1)

1-172: Update Invoice action wiring and payload construction look correct

The props schema, validation headers, query params (replace, replaceSelectedFields), and conditional assembly of the data payload (entity, subsidiary, items, memo, otherRefNum, additionalFields) are all consistent with the related create/update actions and NetSuite expectations.

The only caveat is that this action relies on utils.parseJson for items and additionalFields; once the depth/cycle handling in that utility is corrected (see comment in components/netsuite/common/utils.mjs), this action should behave as intended.

components/netsuite/actions/create-sales-order/create-sales-order.mjs (1)

1-128: Create Sales Order action is well-structured and consistent

The action metadata, prop definitions, and run implementation align with the create-invoice pattern and correctly delegate to app.createSalesOrder with validation headers and a properly assembled payload (including parsed items and additionalFields).

The name "Create Sales Order" correctly reflects the behavior, which is good alignment with prior feedback on action naming. Aside from the shared parseJson utility concerns already noted, this action looks solid.

components/netsuite/actions/list-invoices/list-invoices.mjs (1)

1-61: List Invoices action correctly leverages pagination helper

The action uses app.paginate in the same way as the list-sales-orders action, with appropriate conditional search params and a clear summary message. The for await accumulation into items and return value are straightforward and correct.

No changes needed here.

components/netsuite/actions/create-invoice/create-invoice.mjs (1)

104-147: Create‑invoice action wiring looks correct and consistent

The createInvoice call uses the same flattened options shape as createSalesOrder / updateInvoice, so $, validation headers, replace, and the payload (including parsed items and additionalFields) will be forwarded correctly to _makeRequest. This action is structurally sound once the shared app helpers are fixed.

components/netsuite/actions/update-sales-order/update-sales-order.mjs (1)

110-141: The review comment identifies a critical issue regarding argument handling in the updateSalesOrder call, but this cannot be verified without access to the netsuite.app.mjs implementation. The claim that headers, params, and data are being ignored requires examining the actual function signature and how it processes the opts parameter. Manual code inspection of the app file is necessary to confirm whether the suggested nested opts structure or an app-level fix is required.

Comment on lines +24 to +33
async run({ $ }) {
const {
app,
invoiceId,
} = this;

const response = await app.deleteInvoice({
$,
invoiceId,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "netsuite.app.mjs" | head -5

Repository: PipedreamHQ/pipedream

Length of output: 103


🏁 Script executed:

cat -n ./components/netsuite/netsuite.app.mjs | head -150

Repository: PipedreamHQ/pipedream

Length of output: 5400


🏁 Script executed:

rg -n "deleteInvoice|_makeRequest" ./components/netsuite/netsuite.app.mjs | head -30

Repository: PipedreamHQ/pipedream

Length of output: 561


🏁 Script executed:

sed -n '187,195p' ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 268


🏁 Script executed:

sed -n '265,273p' ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 253


🏁 Script executed:

sed -n '197,210p' ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 366


🏁 Script executed:

rg -n "createInvoice|updateInvoice" ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 123


🏁 Script executed:

sed -n '249,273p' ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 589


🏁 Script executed:

cat -n ./components/netsuite/actions/delete-invoice/delete-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1179


🏁 Script executed:

cat -n ./components/netsuite/actions/create-invoice/create-invoice.mjs | head -50

Repository: PipedreamHQ/pipedream

Length of output: 1941


🏁 Script executed:

sed -n '60,90p' ./components/netsuite/actions/create-invoice/create-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 935


🏁 Script executed:

sed -n '85,130p' ./components/netsuite/actions/create-invoice/create-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 971


🏁 Script executed:

sed -n '20,60p' ./components/netsuite/actions/update-invoice/update-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1118


🏁 Script executed:

grep -n "async run" ./components/netsuite/actions/update-invoice/update-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 89


🏁 Script executed:

sed -n '118,155p' ./components/netsuite/actions/update-invoice/update-invoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 896


🏁 Script executed:

rg -A 3 "async run\(\{ \$ \}\)" ./components/netsuite/actions/*/update-invoice/update-invoice.mjs | head -20

Repository: PipedreamHQ/pipedream

Length of output: 170


$ is ignored by deleteInvoice with current app signature

deleteInvoice is declared as ({ invoiceId, opts } = {}), so passing { $, invoiceId } here sets only invoiceId; $ is dropped and _makeRequest falls back to $ = this. The DELETE request will still execute, but step context and logging are lost. To fix, nest $ under opts:

    const response = await app.deleteInvoice({
-     $,
      invoiceId,
+     opts: {
+       $,
+     },
    });

Alternatively, update deleteInvoice in netsuite.app.mjs to accept top-level options like createInvoice does (signature: createInvoice(opts = {})), which would provide consistency across all invoice methods.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async run({ $ }) {
const {
app,
invoiceId,
} = this;
const response = await app.deleteInvoice({
$,
invoiceId,
});
async run({ $ }) {
const {
app,
invoiceId,
} = this;
const response = await app.deleteInvoice({
invoiceId,
opts: {
$,
},
});
🤖 Prompt for AI Agents
In components/netsuite/actions/delete-invoice/delete-invoice.mjs around lines 24
to 33, the call to app.deleteInvoice currently passes $ at the top-level which
is ignored because deleteInvoice signature is ({ invoiceId, opts } = {}); update
the call to pass the step context inside opts (i.e., call deleteInvoice with
invoiceId and opts: { $ }) so _makeRequest receives the step context and logging
remains intact; alternatively, modify netsuite.app.mjs to change deleteInvoice
to accept a single opts object similar to createInvoice (signature like
deleteInvoice(opts = {})) so top-level options including $ are honored
consistently across invoice methods.

Comment on lines +51 to +59
const response = await app.getSalesOrder({
$,
salesOrderId,
params: {
expandSubResources,
simpleEnumFormat,
fields,
},
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find the netsuite app file
find . -name "netsuite.app.mjs" -o -name "*netsuite*app*" | head -20

Repository: PipedreamHQ/pipedream

Length of output: 186


🏁 Script executed:

# Also locate the file mentioned in the review
find . -path "*netsuite/actions/get-sales-order*" -type f

Repository: PipedreamHQ/pipedream

Length of output: 130


🏁 Script executed:

# Find the netsuite app definition file
find . -path "*netsuite*" -name "*.mjs" | grep -i app | head -10

Repository: PipedreamHQ/pipedream

Length of output: 103


🏁 Script executed:

# Read the get-sales-order action file to see the full context
head -70 ./components/netsuite/actions/get-sales-order/get-sales-order.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1398


🏁 Script executed:

# Read the netsuite app file to see getSalesOrder implementation
cat ./components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 8324


getSalesOrder call is dropping $ and query params with current app signature

getSalesOrder destructures only salesOrderId and opts from its argument object, so the top-level $ and params keys you're passing are ignored. This means expandSubResources, simpleEnumFormat, and fields never reach the API, and _makeRequest falls back to $ = this instead of using the step context. Nest these under opts:

-    const response = await app.getSalesOrder({
-      $,
-      salesOrderId,
-      params: {
-        expandSubResources,
-        simpleEnumFormat,
-        fields,
-      },
-    });
+    const response = await app.getSalesOrder({
+      salesOrderId,
+      opts: {
+        $,
+        params: {
+          expandSubResources,
+          simpleEnumFormat,
+          fields,
+        },
+      },
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const response = await app.getSalesOrder({
$,
salesOrderId,
params: {
expandSubResources,
simpleEnumFormat,
fields,
},
});
const response = await app.getSalesOrder({
salesOrderId,
opts: {
$,
params: {
expandSubResources,
simpleEnumFormat,
fields,
},
},
});
🤖 Prompt for AI Agents
components/netsuite/actions/get-sales-order/get-sales-order.mjs around lines 51
to 59: the current call passes $ and params at the top level but getSalesOrder
only destructures salesOrderId and opts, so those values are ignored; fix by
moving $ and your query params (expandSubResources, simpleEnumFormat, fields)
into the opts property so the call supplies salesOrderId and opts:{ $: <step
context>, params: { expandSubResources, simpleEnumFormat, fields } } ensuring
the step context ($) and query options reach the API.

Comment on lines +37 to +47
const items = [];
const paginator = app.paginate({
fn: app.listSalesOrders,
fnArgs: {
$,
params: {
q: searchQuery,
},
},
maxResults,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

fd -t f "netsuite.app.mjs" --type f

Repository: PipedreamHQ/pipedream

Length of output: 186


🏁 Script executed:

fd -t f "\.mjs$" | grep -E "(netsuite|app)" | head -20

Repository: PipedreamHQ/pipedream

Length of output: 186


🏁 Script executed:

git ls-files | grep -E "netsuite.*app"

Repository: PipedreamHQ/pipedream

Length of output: 101


🏁 Script executed:

cat -n components/netsuite/netsuite.app.mjs | head -200

Repository: PipedreamHQ/pipedream

Length of output: 7245


🏁 Script executed:

wc -l components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 105


🏁 Script executed:

cat -n components/netsuite/actions/list-sales-orders/list-sales-orders.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1763


🏁 Script executed:

grep -n "paginate" components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 90


🏁 Script executed:

sed -n '200,322p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 2553


🏁 Script executed:

sed -n '175,195p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 644


Unbound fn breaks listSalesOrders inside paginate

The paginate method calls fn({...}) at line 299 without binding context. When fn is app.listSalesOrders, the method loses its this binding, causing this._makeRequest to fail with an undefined reference error.

Fix by binding the method:

-    const paginator = app.paginate({
-      fn: app.listSalesOrders,
+    const paginator = app.paginate({
+      fn: app.listSalesOrders.bind(app),

Alternatively, update paginate in netsuite.app.mjs (line 299) to preserve context:

-        const response = await fn({
+        const response = await fn.call(this, {
🤖 Prompt for AI Agents
In components/netsuite/actions/list-sales-orders/list-sales-orders.mjs around
lines 37 to 47, the code passes app.listSalesOrders into paginate unbound which
causes loss of `this` (breaking this._makeRequest inside listSalesOrders); fix
by passing a bound function or wrapper so the method retains its app context
(for example, set fn to app.listSalesOrders.bind(app) or to a small arrow
wrapper that calls app.listSalesOrders(...)); alternatively, update paginate in
netsuite.app.mjs to call the passed function with the app as its receiver (e.g.
fn.call(app, ...)) so the original method context is preserved.

Comment on lines +1 to +44
const parseJson = (input, maxDepth = 100) => {
const seen = new WeakSet();
const parse = (value) => {
if (maxDepth <= 0) {
return value;
}
if (typeof(value) === "string") {
// Only parse if the string looks like a JSON object or array
const trimmed = value.trim();
if (
(trimmed.startsWith("{") && trimmed.endsWith("}")) ||
(trimmed.startsWith("[") && trimmed.endsWith("]"))
) {
try {
return parseJson(JSON.parse(value), maxDepth - 1);
} catch (e) {
return value;
}
}
return value;
} else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) {
if (seen.has(value)) {
return value;
}
seen.add(value);
return Object.entries(value)
.reduce((acc, [
key,
val,
]) => Object.assign(acc, {
[key]: parse(val),
}), {});
} else if (Array.isArray(value)) {
return value.map((item) => parse(item));
}
return value;
};

return parse(input);
};

export default {
parseJson,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix depth handling and circular array detection in parseJson

The current implementation has two important pitfalls:

  • maxDepth is effectively not enforced for nested objects/arrays: parse closes over maxDepth but never updates it, so if (maxDepth <= 0) never changes as recursion proceeds (except when re-entering via parseJson on strings).
  • Arrays are not tracked in seen, so a self-referential array (or cycles involving arrays) can cause infinite recursion / stack overflow.

You can address both by:

  • Passing a depth argument through recursive calls and checking depth >= maxDepth.
  • Treating any non-null object (including arrays) as candidates for cycle detection in the WeakSet.
  • Reusing parse after JSON.parse instead of re-entering parseJson, so a single seen set and depth counter are used consistently.

Example refactor:

-const parseJson = (input, maxDepth = 100) => {
-  const seen = new WeakSet();
-  const parse = (value) => {
-    if (maxDepth <= 0) {
-      return value;
-    }
-    if (typeof(value) === "string") {
-      // Only parse if the string looks like a JSON object or array
-      const trimmed = value.trim();
-      if (
-        (trimmed.startsWith("{") && trimmed.endsWith("}")) ||
-        (trimmed.startsWith("[") && trimmed.endsWith("]"))
-      ) {
-        try {
-          return parseJson(JSON.parse(value), maxDepth - 1);
-        } catch (e) {
-          return value;
-        }
-      }
-      return value;
-    } else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) {
-      if (seen.has(value)) {
-        return value;
-      }
-      seen.add(value);
-      return Object.entries(value)
-        .reduce((acc, [
-          key,
-          val,
-        ]) => Object.assign(acc, {
-          [key]: parse(val),
-        }), {});
-    } else if (Array.isArray(value)) {
-      return value.map((item) => parse(item));
-    }
-    return value;
-  };
-
-  return parse(input);
-};
+const parseJson = (input, maxDepth = 100) => {
+  const seen = new WeakSet();
+
+  const parse = (value, depth = 0) => {
+    if (depth >= maxDepth) {
+      return value;
+    }
+
+    if (typeof value === "string") {
+      // Only parse if the string looks like a JSON object or array
+      const trimmed = value.trim();
+      if (
+        (trimmed.startsWith("{") && trimmed.endsWith("}")) ||
+        (trimmed.startsWith("[") && trimmed.endsWith("]"))
+      ) {
+        try {
+          return parse(JSON.parse(value), depth + 1);
+        } catch (e) {
+          return value;
+        }
+      }
+      return value;
+    }
+
+    if (value && typeof value === "object") {
+      if (seen.has(value)) {
+        return value;
+      }
+      seen.add(value);
+
+      if (Array.isArray(value)) {
+        return value.map((item) => parse(item, depth + 1));
+      }
+
+      return Object.fromEntries(
+        Object.entries(value)
+          .map(([key, val]) => [key, parse(val, depth + 1)]),
+      );
+    }
+
+    return value;
+  };
+
+  return parse(input);
+};

This preserves the external API while making maxDepth meaningful and preventing cycles (including arrays) from blowing the stack.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const parseJson = (input, maxDepth = 100) => {
const seen = new WeakSet();
const parse = (value) => {
if (maxDepth <= 0) {
return value;
}
if (typeof(value) === "string") {
// Only parse if the string looks like a JSON object or array
const trimmed = value.trim();
if (
(trimmed.startsWith("{") && trimmed.endsWith("}")) ||
(trimmed.startsWith("[") && trimmed.endsWith("]"))
) {
try {
return parseJson(JSON.parse(value), maxDepth - 1);
} catch (e) {
return value;
}
}
return value;
} else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) {
if (seen.has(value)) {
return value;
}
seen.add(value);
return Object.entries(value)
.reduce((acc, [
key,
val,
]) => Object.assign(acc, {
[key]: parse(val),
}), {});
} else if (Array.isArray(value)) {
return value.map((item) => parse(item));
}
return value;
};
return parse(input);
};
export default {
parseJson,
};
const parseJson = (input, maxDepth = 100) => {
const seen = new WeakSet();
const parse = (value, depth = 0) => {
if (depth >= maxDepth) {
return value;
}
if (typeof value === "string") {
// Only parse if the string looks like a JSON object or array
const trimmed = value.trim();
if (
(trimmed.startsWith("{") && trimmed.endsWith("}")) ||
(trimmed.startsWith("[") && trimmed.endsWith("]"))
) {
try {
return parse(JSON.parse(value), depth + 1);
} catch (e) {
return value;
}
}
return value;
}
if (value && typeof value === "object") {
if (seen.has(value)) {
return value;
}
seen.add(value);
if (Array.isArray(value)) {
return value.map((item) => parse(item, depth + 1));
}
return Object.fromEntries(
Object.entries(value)
.map(([key, val]) => [key, parse(val, depth + 1)]),
);
}
return value;
};
return parse(input);
};
export default {
parseJson,
};

Comment on lines +202 to +273
getSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
createSalesOrder(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/salesOrder",
...opts,
});
},
updateSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
method: "PATCH",
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
deleteSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
method: "DELETE",
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
listInvoices(opts = {}) {
return this._makeRequest({
path: "/invoice",
...opts,
});
},
getInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
path: `/invoice/${invoiceId}`,
...opts,
});
},
createInvoice(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/invoice",
...opts,
});
},
updateInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
method: "PATCH",
path: `/invoice/${invoiceId}`,
...opts,
});
},
deleteInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
method: "DELETE",
path: `/invoice/${invoiceId}`,
...opts,
});
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd components/netsuite && find . -name "*.mjs" -o -name "*.js" | head -20

Repository: PipedreamHQ/pipedream

Length of output: 589


🏁 Script executed:

cd components/netsuite && ls -la

Repository: PipedreamHQ/pipedream

Length of output: 441


🏁 Script executed:

cd components/netsuite && wc -l netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 85


🏁 Script executed:

cd components/netsuite && sed -n '180,280p' netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 2294


🏁 Script executed:

cd components/netsuite && grep -r "getSalesOrder\|updateSalesOrder\|getInvoice\|updateInvoice" --include="*.mjs" --include="*.js" -B 3 -A 3

Repository: PipedreamHQ/pipedream

Length of output: 2781


🏁 Script executed:

cd components/netsuite && find . -name "actions" -o -name "actions.mjs" -o -name "*action*.mjs"

Repository: PipedreamHQ/pipedream

Length of output: 74


🏁 Script executed:

cd components/netsuite && ls -la actions/ 2>/dev/null || find . -path "*action*" -type f | head -20

Repository: PipedreamHQ/pipedream

Length of output: 827


🏁 Script executed:

cd components/netsuite && find . -type f -name "*.mjs" | head -20

Repository: PipedreamHQ/pipedream

Length of output: 589


🏁 Script executed:

cd components/netsuite && cat -n netsuite.app.mjs | sed -n '1,50p'

Repository: PipedreamHQ/pipedream

Length of output: 1802


🏁 Script executed:

cd components/netsuite && wc -l netsuite.app.mjs && echo "---" && head -100 netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 2884


🏁 Script executed:

cd components/netsuite && grep -n "actions\|propDefinitions" netsuite.app.mjs | head -20

Repository: PipedreamHQ/pipedream

Length of output: 87


🏁 Script executed:

cd components/netsuite && sed -n '200,280p' netsuite.app.mjs | cat -n

Repository: PipedreamHQ/pipedream

Length of output: 2344


🏁 Script executed:

cd components/netsuite && find . -type d -name actions

Repository: PipedreamHQ/pipedream

Length of output: 74


🏁 Script executed:

cd components/netsuite && ls -la

Repository: PipedreamHQ/pipedream

Length of output: 441


🏁 Script executed:

cd components/netsuite && git ls-files | head -30

Repository: PipedreamHQ/pipedream

Length of output: 576


🏁 Script executed:

git ls-files components/netsuite/ | head -40

Repository: PipedreamHQ/pipedream

Length of output: 856


🏁 Script executed:

git ls-files components/netsuite/ | grep -E "\.(mjs|js)$"

Repository: PipedreamHQ/pipedream

Length of output: 823


🏁 Script executed:

cat components/netsuite/netsuite.app.mjs | sed -n '200,280p'

Repository: PipedreamHQ/pipedream

Length of output: 1777


🏁 Script executed:

cat components/netsuite/netsuite.app.mjs | grep -n "getSalesOrder\|getInvoice\|updateSalesOrder\|updateInvoice\|deleteSalesOrder\|deleteInvoice" | head -20

Repository: PipedreamHQ/pipedream

Length of output: 211


🏁 Script executed:

wc -l components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 105


🏁 Script executed:

sed -n '200,300p' components/netsuite/netsuite.app.mjs | cat -n

Repository: PipedreamHQ/pipedream

Length of output: 2913


🏁 Script executed:

rg "getSalesOrder|getInvoice|updateSalesOrder|updateInvoice" components/netsuite/ -A 2 -B 2

Repository: PipedreamHQ/pipedream

Length of output: 2745


🏁 Script executed:

find components/netsuite -name "*action*" -type f

Repository: PipedreamHQ/pipedream

Length of output: 47


🏁 Script executed:

ls -la components/netsuite/actions/

Repository: PipedreamHQ/pipedream

Length of output: 827


🏁 Script executed:

cat components/netsuite/actions/getSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

cat components/netsuite/actions/updateSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

cat components/netsuite/actions/getInvoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 139


🏁 Script executed:

sed -n '200,280p' components/netsuite/netsuite.app.mjs | cat -n

Repository: PipedreamHQ/pipedream

Length of output: 2344


🏁 Script executed:

grep -n "getSalesOrder\|getInvoice\|updateSalesOrder" components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 136


🏁 Script executed:

sed -n '202,273p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1599


🏁 Script executed:

cat components/netsuite/actions/updateSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

cat components/netsuite/actions/updateInvoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

rg "this\.app\." components/netsuite/actions/ -A 2 -B 2 | head -60

Repository: PipedreamHQ/pipedream

Length of output: 47


🏁 Script executed:

cat components/netsuite/actions/getSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

cat components/netsuite/actions/createSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

sed -n '202,240p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 914


🏁 Script executed:

ast-grep --pattern $'getSalesOrder($_) {
  $$$
}'

Repository: PipedreamHQ/pipedream

Length of output: 47


🏁 Script executed:

python3 << 'EOF'
import re

with open('components/netsuite/netsuite.app.mjs', 'r') as f:
    content = f.read()

# Find getSalesOrder method
match = re.search(r'getSalesOrder\([^)]*\)\s*\{[^}]*\}', content, re.DOTALL)
if match:
    print("getSalesOrder signature:")
    print(match.group(0)[:200])
    print()

# Find updateSalesOrder  
match = re.search(r'updateSalesOrder\([^)]*\)\s*\{[^}]*\}', content, re.DOTALL)
if match:
    print("updateSalesOrder signature:")
    print(match.group(0)[:200])

EOF

Repository: PipedreamHQ/pipedream

Length of output: 151


🏁 Script executed:

head -280 components/netsuite/netsuite.app.mjs | tail -80 | cat -n

Repository: PipedreamHQ/pipedream

Length of output: 2327


🏁 Script executed:

ls -1 components/netsuite/actions/

Repository: PipedreamHQ/pipedream

Length of output: 226


🏁 Script executed:

cat components/netsuite/actions/getSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

cat components/netsuite/actions/updateSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

python3 << 'EOF'
import os
import re

actions_dir = 'components/netsuite/actions'
for filename in os.listdir(actions_dir):
    if filename.endswith('.mjs'):
        filepath = os.path.join(actions_dir, filename)
        with open(filepath, 'r') as f:
            content = f.read()
            # Find calls to this.app
            calls = re.findall(r'this\.app\.(\w+)\([^)]*\)', content)
            if calls and any(x in ['getSalesOrder', 'updateSalesOrder', 'getInvoice', 'updateInvoice', 'deleteSalesOrder', 'deleteInvoice'] for x in calls):
                print(f"\n{filename}:")
                # Get the actual call
                match = re.search(r'return this\.app\.(\w+)\(\s*\{[^}]*\}\s*\)', content, re.DOTALL)
                if match:
                    full_match = re.search(r'return this\.app\.\w+\(\s*\{[^}]*\}\s*\)', content, re.DOTALL)
                    if full_match:
                        call_text = full_match.group(0)
                        # Limit display
                        print(call_text[:300] if len(call_text) < 300 else call_text[:300] + "...")
EOF

Repository: PipedreamHQ/pipedream

Length of output: 151


🏁 Script executed:

cat components/netsuite/actions/updateSalesOrder.mjs | grep -A 20 "return this.app"

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

cat components/netsuite/actions/updateInvoice.mjs | grep -A 20 "return this.app"

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

python3 << 'EOF'
with open('components/netsuite/netsuite.app.mjs', 'r') as f:
    lines = f.readlines()
    
# Print lines 202-240 with line numbers
for i in range(201, min(240, len(lines))):
    print(f"{i+1}: {lines[i]}", end='')
EOF

Repository: PipedreamHQ/pipedream

Length of output: 151


🏁 Script executed:

sed -n '100,200p' components/netsuite/netsuite.app.mjs | grep -A 30 "_makeRequest"

Repository: PipedreamHQ/pipedream

Length of output: 390


🏁 Script executed:

grep -n "_makeRequest" components/netsuite/netsuite.app.mjs | head -5

Repository: PipedreamHQ/pipedream

Length of output: 241


🏁 Script executed:

sed -n '50,150p' components/netsuite/netsuite.app.mjs | cat -n

Repository: PipedreamHQ/pipedream

Length of output: 3701


🏁 Script executed:

head -100 components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 2859


🏁 Script executed:

cat components/netsuite/actions/updateSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

python3 << 'EOF'
# Simulate the destructuring
call_obj = {
    '$': 'context',
    'salesOrderId': '123',
    'data': {'field': 'value'}
}

# Current signature: updateSalesOrder({ salesOrderId, opts } = {})
def current_signature(**kwargs):
    salesOrderId = kwargs.pop('salesOrderId', None)
    opts = kwargs.pop('opts', None)
    remaining = kwargs
    print(f"salesOrderId: {salesOrderId}")
    print(f"opts: {opts}")
    print(f"remaining keys: {list(remaining.keys())}")
    
# Proposed signature: updateSalesOrder(opts = {})
def proposed_signature(opts={}):
    salesOrderId = opts.pop('salesOrderId', None)
    rest = opts
    print(f"salesOrderId: {salesOrderId}")
    print(f"rest keys: {list(rest.keys())}")

print("Current signature behavior:")
current_signature(**call_obj)
print("\nProposed signature behavior:")
proposed_signature(call_obj.copy())
EOF

Repository: PipedreamHQ/pipedream

Length of output: 151


🏁 Script executed:

sed -n '1,100p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 2859


🏁 Script executed:

sed -n '180,220p' components/netsuite/netsuite.app.mjs

Repository: PipedreamHQ/pipedream

Length of output: 1020


🏁 Script executed:

cat components/netsuite/actions/getSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 142


🏁 Script executed:

cat components/netsuite/actions/getInvoice.mjs

Repository: PipedreamHQ/pipedream

Length of output: 139


🏁 Script executed:

cat components/netsuite/actions/createSalesOrder.mjs

Repository: PipedreamHQ/pipedream

Length of output: 145


🏁 Script executed:

rg "\.getSalesOrder\(|\.updateSalesOrder\(|\.getInvoice\(|\.updateInvoice\(" components/netsuite/ -B 2 -A 2

Repository: PipedreamHQ/pipedream

Length of output: 1691


Update get/update/delete helpers to prevent silent discard of top-level options

The current helper signatures (e.g., getSalesOrder({ salesOrderId, opts } = {})) destructure salesOrderId and opts separately, but when actions call these methods with top-level parameters like { $, salesOrderId, data, params }, the $ and additional options are completely discarded because they don't match the destructuring pattern. This breaks SDK context flow and data transmission for PATCH/DELETE operations.

Refactor all six helpers to use a single opts parameter and extract the ID:

-    getSalesOrder({
-      salesOrderId, opts,
-    } = {}) {
-      return this._makeRequest({
-        path: `/salesOrder/${salesOrderId}`,
-        ...opts,
-      });
-    },
+    getSalesOrder(opts = {}) {
+      const {
+        salesOrderId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        path: `/salesOrder/${salesOrderId}`,
+        ...rest,
+      });
+    },
@@
-    updateSalesOrder({
-      salesOrderId, opts,
-    } = {}) {
-      return this._makeRequest({
-        method: "PATCH",
-        path: `/salesOrder/${salesOrderId}`,
-        ...opts,
-      });
-    },
-    deleteSalesOrder({
-      salesOrderId, opts,
-    } = {}) {
-      return this._makeRequest({
-        method: "DELETE",
-        path: `/salesOrder/${salesOrderId}`,
-        ...opts,
-      });
-    },
+    updateSalesOrder(opts = {}) {
+      const {
+        salesOrderId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        method: "PATCH",
+        path: `/salesOrder/${salesOrderId}`,
+        ...rest,
+      });
+    },
+    deleteSalesOrder(opts = {}) {
+      const {
+        salesOrderId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        method: "DELETE",
+        path: `/salesOrder/${salesOrderId}`,
+        ...rest,
+      });
+    },
@@
-    getInvoice({
-      invoiceId, opts,
-    } = {}) {
-      return this._makeRequest({
-        path: `/invoice/${invoiceId}`,
-        ...opts,
-      });
-    },
+    getInvoice(opts = {}) {
+      const {
+        invoiceId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        path: `/invoice/${invoiceId}`,
+        ...rest,
+      });
+    },
@@
-    updateInvoice({
-      invoiceId, opts,
-    } = {}) {
-      return this._makeRequest({
-        method: "PATCH",
-        path: `/invoice/${invoiceId}`,
-        ...opts,
-      });
-    },
-    deleteInvoice({
-      invoiceId, opts,
-    } = {}) {
-      return this._makeRequest({
-        method: "DELETE",
-        path: `/invoice/${invoiceId}`,
-        ...opts,
-      });
-    },
+    updateInvoice(opts = {}) {
+      const {
+        invoiceId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        method: "PATCH",
+        path: `/invoice/${invoiceId}`,
+        ...rest,
+      });
+    },
+    deleteInvoice(opts = {}) {
+      const {
+        invoiceId,
+        ...rest
+      } = opts;
+      return this._makeRequest({
+        method: "DELETE",
+        path: `/invoice/${invoiceId}`,
+        ...rest,
+      });
+    },

This ensures all parameters including $, data, params, and headers pass through to _makeRequest.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
getSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
createSalesOrder(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/salesOrder",
...opts,
});
},
updateSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
method: "PATCH",
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
deleteSalesOrder({
salesOrderId, opts,
} = {}) {
return this._makeRequest({
method: "DELETE",
path: `/salesOrder/${salesOrderId}`,
...opts,
});
},
listInvoices(opts = {}) {
return this._makeRequest({
path: "/invoice",
...opts,
});
},
getInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
path: `/invoice/${invoiceId}`,
...opts,
});
},
createInvoice(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/invoice",
...opts,
});
},
updateInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
method: "PATCH",
path: `/invoice/${invoiceId}`,
...opts,
});
},
deleteInvoice({
invoiceId, opts,
} = {}) {
return this._makeRequest({
method: "DELETE",
path: `/invoice/${invoiceId}`,
...opts,
});
},
getSalesOrder(opts = {}) {
const {
salesOrderId,
...rest
} = opts;
return this._makeRequest({
path: `/salesOrder/${salesOrderId}`,
...rest,
});
},
createSalesOrder(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/salesOrder",
...opts,
});
},
updateSalesOrder(opts = {}) {
const {
salesOrderId,
...rest
} = opts;
return this._makeRequest({
method: "PATCH",
path: `/salesOrder/${salesOrderId}`,
...rest,
});
},
deleteSalesOrder(opts = {}) {
const {
salesOrderId,
...rest
} = opts;
return this._makeRequest({
method: "DELETE",
path: `/salesOrder/${salesOrderId}`,
...rest,
});
},
listInvoices(opts = {}) {
return this._makeRequest({
path: "/invoice",
...opts,
});
},
getInvoice(opts = {}) {
const {
invoiceId,
...rest
} = opts;
return this._makeRequest({
path: `/invoice/${invoiceId}`,
...rest,
});
},
createInvoice(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/invoice",
...opts,
});
},
updateInvoice(opts = {}) {
const {
invoiceId,
...rest
} = opts;
return this._makeRequest({
method: "PATCH",
path: `/invoice/${invoiceId}`,
...rest,
});
},
deleteInvoice(opts = {}) {
const {
invoiceId,
...rest
} = opts;
return this._makeRequest({
method: "DELETE",
path: `/invoice/${invoiceId}`,
...rest,
});
},
🤖 Prompt for AI Agents
In components/netsuite/netsuite.app.mjs around lines 202 to 273, the
get/update/delete helpers (getSalesOrder, updateSalesOrder, deleteSalesOrder,
getInvoice, updateInvoice, deleteInvoice) currently destructure their ID and an
inner opts object which causes top-level options like $/data/params/headers to
be dropped; change each signature to accept a single opts = {} parameter, pull
the id from opts (e.g., const { salesOrderId } = opts or invoiceId for invoice
helpers) and then call this._makeRequest using the resolved path and spread the
entire opts so all top-level properties are forwarded (keep
method:"PATCH"/"DELETE" where applicable). Ensure you do not lose other opts
when building the request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Netsuite

2 participants