Can Functions be Defined Inside a Single Pipedream Step in Node.js?

This topic was automatically generated from Slack. You can find the original thread here.

I have a really long node js Pipedream step that needs to stay one step. It would read much better if I could define functions inside the Pipedream step, and I was wondering if there was a way to do this?

Yes, you can define functions within a Pipedream Node.js step to organize your code better and make it more readable. Here’s a basic example to illustrate how you might structure your code with functions inside a Pipedream step: export default defineComponent({ async run({steps, $}) { // Define a function within the step function myCustomFunction(param) { // Function logic here return `Processed ${param}`; } // Call the function within the same step const result = myCustomFunction("my input"); // Use the result of the function console.log(result); // Return the result so it can be used in subsequent steps return result; }, }) In this example, myCustomFunction is defined within the run method and can be called anywhere within the same step. This approach allows you to encapsulate functionality, making your code cleaner and easier to read, especially for complex logic.

I believe I can also define methods on a component itself and reference them in the run method using this.methodName(), correct? Can you tell me more about how to do that?

Yes, you’re correct. You can define helper functions within the methods property of your component and access these functions within the run method or within other methods. These methods can be accessed using this.<method-name>(). Here’s a basic example to illustrate how you can define and use methods within a component: export default defineComponent({ methods: { // Define a method named "random" random() { // This method returns a random number return Math.random(); }, }, async run({steps, $}) { // Use the "random" method within the run method const randomNum = this.random(); // Return the random number return randomNum; }, }) In this example, a method named random is defined within the methods property. This method returns a random number when called. Within the run method, you can call this random method using this.random(), and it will execute the code defined in the random method, returning a random number in this case. Remember, this is a simple example to demonstrate the concept. You can define more complex methods based on your requirements and use them similarly within the run method or other methods.

You can also define functions outside of the defineComponent block.

Although you don’t have the exact same execution context out there, so be careful.

yes totally. We use both methods internally. Adding methods gives you access to other methods and the values of props via this , which can be nice if you’re developing methods that rely on those, but both work

It would be cool if we could define generic/reusable methods on apps somehow. :thinking_face:

Because often, reusable code is tied to a specific app/action.

Something like this, for example:

export default defineComponent({
  props: {
    slack: {
      type: "app",
      app: "slack",
    },
  },
  async run({ steps, $ }) {
    this.slack.my_custom_method();
    // Pipedream could also provide generic methods for customers.
    // In fact, all actions could be exposed as methods as well.
    // Basically, action props are like method parameters.
    this.slack.pipedream_method();
  }
})

For example, we have this code all over the place in our workspace:

    const resp = await (await fetch("https://slack.com/api/chat.postMessage", {
      method: "POST",
      body: JSON.stringify({...}),
      headers: {
        Authorization: `Bearer ${this.slack.$auth.bot_token}`,
        "Content-Type": "application/json",
      },
    })).json();

    console.log(resp);
    if (!resp.ok) throw new Error("Failed to send message to Slack.");

It would be so much easier (and cleaner) if we could define it as a reusable method, and only supply the json body.

Something like this.slack.send_custom_message({ ... });

All methods defined in the app file are actually available for use inside any component. You can import the app file as an npm package:

import slack from “@pipedream/slack”

Pass slack as the app prop, and all the methods defined on the app are available via this.

It looks like we don’t have the send message method defined in the Slack app file but feel free to submit a PR to add any method and it’ll be available on the app: https://github.com/PipedreamHQ/pipedream/blob/master/components/slack/slack.app.mjs .

Agreed re: exposing all actions as methods, as well.

It would be even better/easier if we didn’t need the import, and could call methods directly on the instantiated object/app (from the props).

But this is a start. Thank you! :pray:

And custom customer methods would basically be easily supported if there was a way to globally monkey patch the apps.

Something like this:

app.my_custom_method = (params) => {
  // do stuff
  return "something";
}

Which could be easily run internally by Pipedream every time the app is included as a prop in a code step.

Both JS & Python support monkey patching very cleanly, so this approach would work for everyone.

And for customers who are looking for a way to package reusable code… they could just do it inside of a generic app. Something like a utils app that can be easily included as a prop wherever necessary.

I think you guys were still looking into ways to offer that ability to customer (reuse generic code/functions).

I think this would be a pretty cool & clean way to do it. :man-shrugging:

Imagine, it could be this simple:

Or even just like this (which would work a bit differently than monkey patching apps though).

And it’s not even really an app/prop at that point. :thinking_face:

image.png

Anyway, just sharing ideas!

:wave:

For sure! We’ve discussed similar ideas, will share with the team

Continuing the thoughts…

If libs are not props, it could be simplified even further:

image.png