Skip to content

Commit cad7b84

Browse files
Pipedream Utils Components (#15925)
* add helper functions * add formatting * bump package.json * pnpm * fix app file * fix key * fix component import * fix component import * add missing import * fixes * fix import * fix imports * pnpm
1 parent fae2ff9 commit cad7b84

File tree

62 files changed

+3527
-23
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3527
-23
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Overview
2+
3+
The Pipedream Utils app is a set of pre-built functions that streamline common tasks in your workflows. It acts like a Swiss Army knife for developers, providing essential tools such as format conversion, date manipulation, and text processing. By leveraging these functions, you can reduce the boilerplate code needed for routine operations, speeding up the development of intricate automations. The Helper Functions API can be a game changer when it comes to tasks like parsing dates in user-friendly formats, encoding and decoding data, or generating UUIDs, making them more efficient and less error-prone.
4+
5+
# Example Use Cases
6+
7+
- **Format User Input for Database Storage**
8+
In an app where users submit data through forms, the Helper Functions API can be used to sanitize and format user input before it is stored in a database, such as Airtable. This ensures that data is clean and uniform, simplifying retrieval and analysis.
9+
10+
- **Process Webhook Payloads**
11+
When dealing with incoming webhooks from apps like GitHub, the Helper Functions API can parse and transform JSON payloads. This allows you to extract specific data points and reformat them for use in other apps like Slack for team notifications or JIRA for creating issues.
12+
13+
- **Automate Content Publication Workflow**
14+
A content calendar on Google Sheets can trigger a workflow that uses Helper Functions to parse dates and format post titles. The workflow could then use this data to automatically schedule and publish content on platforms like WordPress or social media apps.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { ConfigurationError } from "@pipedream/platform";
2+
import pipedream_utils from "../../pipedream_utils.app.mjs";
3+
import commonDateTime from "../../common/date-time/commonDateTime.mjs";
4+
import {
5+
DATE_FORMAT_PARSE_MAP, DEFAULT_FORMAT_VALUE,
6+
} from "../../common/date-time/dateFormats.mjs";
7+
import { DATE_TIME_UNITS } from "../../common/date-time/dateTimeUnits.mjs";
8+
import sugar from "sugar";
9+
const OPERATION_OPTIONS = {
10+
ADD: "Add",
11+
SUBTRACT: "Subtract",
12+
};
13+
export default {
14+
...commonDateTime,
15+
name: "Formatting - [Date/Time] Add/Subtract Time",
16+
description: "Add or subtract time from a given input",
17+
key: "pipedream_utils-add-subtract-time",
18+
version: "0.0.5",
19+
type: "action",
20+
props: {
21+
...commonDateTime.props,
22+
operation: {
23+
label: "Operation",
24+
description: "Whether to add or subtract time.",
25+
type: "string",
26+
options: Object.values(OPERATION_OPTIONS),
27+
},
28+
duration: {
29+
label: "Duration",
30+
description: "The duration for the operation. You can use the shorthand duration, for example: `1s`, `1m`, `1h`, `1d`, `1w`, `1y` equal one second, minute, hour, day, week, and year respectively",
31+
type: "string",
32+
},
33+
outputFormat: {
34+
propDefinition: [
35+
pipedream_utils,
36+
"outputFormat",
37+
],
38+
},
39+
},
40+
methods: {
41+
...commonDateTime.methods,
42+
getOperationMilliseconds(str) {
43+
let result = 0;
44+
const {
45+
second, minute, hour, day, week, year,
46+
} = DATE_TIME_UNITS;
47+
Object.entries({
48+
s: second,
49+
m: minute,
50+
h: hour,
51+
d: day,
52+
w: week,
53+
y: year,
54+
}).forEach(([
55+
identifier,
56+
multiplier,
57+
]) => {
58+
const substr = str.match(new RegExp(`[0-9]+\\s*${identifier}`))?.[0];
59+
if (substr) {
60+
const value = Number(substr.match(/[0-9]+/));
61+
result += value * multiplier;
62+
}
63+
});
64+
return result;
65+
},
66+
},
67+
async run({ $ }) {
68+
const {
69+
operation, duration, outputFormat,
70+
} = this;
71+
const dateObj = this.getDateFromInput();
72+
const value = dateObj.valueOf();
73+
let amount = this.getOperationMilliseconds(duration);
74+
if (operation === OPERATION_OPTIONS.SUBTRACT)
75+
amount *= -1;
76+
const result = value + amount;
77+
const format = outputFormat ?? this.inputFormat ?? DEFAULT_FORMAT_VALUE;
78+
try {
79+
const { outputFn } = DATE_FORMAT_PARSE_MAP.get(format);
80+
const output = outputFn(sugar.Date.create(result));
81+
$.export("$summary", `Successfully ${operation === OPERATION_OPTIONS.SUBTRACT
82+
? "subtracted"
83+
: "added"} time`);
84+
return output;
85+
}
86+
catch (err) {
87+
console.log("Error parsing date", err);
88+
throw new ConfigurationError("**Parse error** - check your input and if the selected format is correct.");
89+
}
90+
},
91+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// legacy_hash_id: a_0Mio28
2+
import pipedream_utils from "../../pipedream_utils.app.mjs";
3+
4+
export default {
5+
key: "pipedream_utils-base64-decode-string",
6+
name: "Helper Functions - Base64 Decode String",
7+
description: "Accepts a base64-encoded string, returns a decoded UTF-8 string",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
pipedream_utils,
12+
data: {
13+
type: "string",
14+
},
15+
},
16+
async run({ $ }) {
17+
const buffer = Buffer.from(this.data, "base64");
18+
$.export("data", buffer.toString("utf8"));
19+
},
20+
};
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import pipedream_utils from "../../pipedream_utils.app.mjs";
2+
3+
export default {
4+
key: "pipedream_utils-compare-arrays",
5+
name: "Helper Functions - Compare Arrays",
6+
description: "Get the difference, intersection, union, or symetric difference of two arrays/sets.",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
pipedream_utils,
11+
array1: {
12+
type: "string[]",
13+
label: "Array 1",
14+
description: "Array to compare to second array",
15+
default: [],
16+
},
17+
array2: {
18+
type: "string[]",
19+
label: "Array 2",
20+
description: "Array to be compared with first array",
21+
default: [],
22+
},
23+
actionType: {
24+
type: "string",
25+
label: "Compare Action",
26+
description: "Type of action to perform on the arrays",
27+
options: [
28+
"difference",
29+
"union",
30+
"intersection",
31+
"symmetric difference",
32+
],
33+
},
34+
},
35+
methods: {
36+
getDifference(set1, set2) {
37+
return new Set([
38+
...set1,
39+
].filter((x) => !set2.has(x)));
40+
},
41+
getIntersection(set1, set2) {
42+
return new Set([
43+
...set1,
44+
].filter((x) => set2.has(x)));
45+
},
46+
getUnion(set1, set2) {
47+
for (const elem of set2) {
48+
set1.add(elem);
49+
}
50+
return set1;
51+
},
52+
getSymmetricDifference(set1, set2) {
53+
for (const elem of set2) {
54+
if (set1.has(elem)) {
55+
set1.delete(elem);
56+
} else {
57+
set1.add(elem);
58+
}
59+
}
60+
return set1;
61+
},
62+
},
63+
run() {
64+
const set1 = new Set(this.array1);
65+
const set2 = new Set(this.array2);
66+
67+
let results;
68+
69+
switch (this.actionType) {
70+
case "difference": {
71+
results = this.getDifference(set1, set2);
72+
break;
73+
}
74+
case "union": {
75+
results = this.getUnion(set1, set2);
76+
break;
77+
}
78+
case "intersection": {
79+
results = this.getIntersection(set1, set2);
80+
break;
81+
}
82+
case "symmetric difference": {
83+
results = this.getSymmetricDifference(set1, set2);
84+
break;
85+
}
86+
default:
87+
throw new Error(`Unknown action type: ${this.actionType}`);
88+
}
89+
90+
return Array.from(results);
91+
},
92+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import commonDateTime from "../../common/date-time/commonDateTime.mjs";
2+
import pipedream_utils from "../../pipedream_utils.app.mjs";
3+
import { DATE_TIME_UNITS } from "../../common/date-time/dateTimeUnits.mjs";
4+
export default {
5+
...commonDateTime,
6+
name: "Formatting - [Date/Time] Compare Dates",
7+
description: "Get the duration between two dates in days, hours, minutes, and seconds along with checking if they are the same.",
8+
key: "pipedream_utils-compare-dates",
9+
version: "0.0.5",
10+
type: "action",
11+
props: {
12+
...commonDateTime.props,
13+
inputDate: {
14+
propDefinition: [
15+
pipedream_utils,
16+
"inputDate",
17+
],
18+
label: "Start Date",
19+
description: "Enter start date string, in the format defined in `Input Format`. If the start date is after the end date, these dates will be swapped and in the output `datesSwapped` will be set to `true`.",
20+
},
21+
endDate: {
22+
propDefinition: [
23+
pipedream_utils,
24+
"inputDate",
25+
],
26+
label: "End Date",
27+
description: "Enter end date string, in the format defined in `Input Format`. Timezone is assumed the same for both dates if not explicitly set.",
28+
},
29+
},
30+
async run({ $ }) {
31+
const startDateObj = this.getDateFromInput(this.inputDate);
32+
const endDateObj = this.getDateFromInput(this.endDate);
33+
const startValue = startDateObj.valueOf();
34+
const endValue = endDateObj.valueOf();
35+
const datesSwapped = startValue > endValue;
36+
let result = "equal";
37+
let remainingValue = Math.abs(endValue - startValue);
38+
if (remainingValue) {
39+
const arrResults = [];
40+
const arrUnits = Object.entries(DATE_TIME_UNITS).sort((a, b) => b[1] - a[1]);
41+
for (const [
42+
word,
43+
unit,
44+
] of arrUnits) {
45+
const amount = Math.floor(remainingValue / unit);
46+
if (amount) {
47+
arrResults.push(`${amount} ${amount === 1
48+
? word
49+
: `${word}s`}`);
50+
remainingValue %= unit;
51+
if (!remainingValue)
52+
break;
53+
}
54+
}
55+
result = arrResults.join(", ");
56+
}
57+
$.export("$summary", "Successfully compared dates");
58+
return {
59+
datesSwapped,
60+
result,
61+
};
62+
},
63+
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { axios } from "@pipedream/platform";
2+
import pipedream_utils from "../../pipedream_utils.app.mjs";
3+
4+
export default {
5+
key: "pipedream_utils-convert-currency",
6+
name: "Helper Functions - Convert Currency",
7+
description: "Convert an amount between currencies. [See the documentation](https://www.frankfurter.app/docs/)",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
pipedream_utils,
12+
fromCurrency: {
13+
type: "string",
14+
label: "From Currency",
15+
description: "The currency to convert from",
16+
async options() {
17+
return this.getCurrencyOptions();
18+
},
19+
},
20+
toCurrency: {
21+
type: "string",
22+
label: "To Currency",
23+
description: "The currency to convert to",
24+
async options() {
25+
return this.getCurrencyOptions();
26+
},
27+
},
28+
value: {
29+
type: "string",
30+
label: "Value",
31+
description: "The value to convert",
32+
},
33+
},
34+
methods: {
35+
async getCurrencyOptions() {
36+
const currencies = await this.getCurrencies();
37+
const options = [];
38+
for (const [
39+
key,
40+
value,
41+
] of Object.entries(currencies)) {
42+
options.push({
43+
value: key,
44+
label: value,
45+
});
46+
}
47+
return options;
48+
},
49+
getCurrencies($ = this) {
50+
return axios($, {
51+
url: "https://api.frankfurter.app/currencies",
52+
});
53+
},
54+
convertCurrency($ = this) {
55+
return axios($, {
56+
url: "https://api.frankfurter.app/latest",
57+
params: {
58+
from: this.fromCurrency,
59+
to: this.toCurrency,
60+
amount: this.value,
61+
},
62+
});
63+
},
64+
},
65+
async run({ $ }) {
66+
const response = await this.convertCurrency($);
67+
$.export("$summary", `${this.value} ${this.fromCurrency} = ${response.rates[this.toCurrency]} ${this.toCurrency}`);
68+
return response;
69+
},
70+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { parseHTML } from "linkedom";
2+
import showdown from "showdown";
3+
import pipedream_utils from "../../pipedream_utils.app.mjs";
4+
export default {
5+
name: "Formatting - [Text] Convert HTML to Markdown",
6+
description: "Convert valid HTML to Markdown text",
7+
key: "pipedream_utils-convert-html-to-markdown",
8+
version: "0.0.6",
9+
type: "action",
10+
props: {
11+
pipedream_utils,
12+
input: {
13+
label: "Input",
14+
description: "HTML string to be converted to Markdown",
15+
type: "string",
16+
},
17+
},
18+
async run({ $ }) {
19+
const { input } = this;
20+
const converter = new showdown.Converter();
21+
const dom = parseHTML("");
22+
const result = converter.makeMarkdown(input, dom.window.document);
23+
$.export("$summary", "Successfully converted to Markdown");
24+
return result;
25+
},
26+
};

0 commit comments

Comments
 (0)