-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Add Csvbox integration with import event trigger and sample row functionality #18982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 11 commits
bd37d5b
6dc70d3
fca35f3
5cc5ea5
b099d8b
fa29835
89914a0
fd3ca8a
b052912
f3afbbc
087a246
2c34709
46da2a6
e1ac262
c00ad1c
b5fe1e7
1e698d7
769aa4c
c795bbc
38005c6
abefc08
c5c94f0
831d74a
5bab81a
345d8bc
f4508d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| const BASE_URL = "https://api.csvbox.io/1.1/pipedream"; | ||
|
|
||
| export default { | ||
| BASE_URL | ||
| }; |
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is a source component please rename the component to something like Also make sure the name of the file matches the key prop in the component! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| import app from "../csvbox.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "csvbox-new-row", | ||
| name: "Import New Row", | ||
| description: "Emit new events when a new row is added to a CSVBox sheet", | ||
| version: "0.0.1", | ||
| type: "source", | ||
| dedupe: "unique", | ||
| props: { | ||
| db: "$.service.db", | ||
| app, | ||
| sheetId: { | ||
| propDefinition: [app, "sheetId"], | ||
| description: "Select the sheet to receive data from", | ||
| }, | ||
| http: "$.interface.http", | ||
| }, | ||
| hooks: { | ||
| async activate() { | ||
| if (!this.sheetId) { | ||
| throw new Error("Sheet selection is required before activation."); | ||
| } | ||
|
|
||
| try { | ||
| const { data } = await this.app.createHook({ | ||
| data: { | ||
| sheet_slug: this.sheetId, | ||
| webhook_url: this.http.endpoint, | ||
| }, | ||
| }); | ||
|
|
||
| const { webhookId, sample_response } = data; | ||
| this._setHookID(webhookId); | ||
|
|
||
| if (!Array.isArray(sample_response) || sample_response.length === 0) { | ||
| throw new Error("Unable to fetch sample data from selected sheet."); | ||
| } | ||
|
|
||
| const first = sample_response[0]; | ||
| const sampleId = `sample_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`; | ||
| this.$emit({ | ||
| import_id: sampleId, | ||
| sheet_id: this.sheetId, | ||
| sheet_name: first.sheet_name || "Sample Data", | ||
| row_number: first.row_number || 1, | ||
| row_data: first.row_data || first, | ||
| total_rows: first.total_rows || 10, | ||
| env_name: first.env_name || "default", | ||
| custom_fields: first.custom_fields || { user_id: "default123" }, | ||
| import_description: first.import_description || "This is a sample test import", | ||
| original_filename: first.original_filename || "product_details.csv", | ||
| }, { | ||
| id: sampleId, | ||
| summary: `Sample data loaded from sheet - ${first.sheet_name} `, | ||
SumitYewale-Thalia marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ts: Date.now(), | ||
| }); | ||
|
|
||
| this._setSampleRow(first); | ||
| } catch (err) { | ||
| console.error("Error during source activation:", err); | ||
| throw new Error(err?.message || "Failed to register webhook or fetch sample data."); | ||
| } | ||
SumitYewale-Thalia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }, | ||
| async deactivate() { | ||
| try { | ||
| const hookId = this._getHookID(); | ||
| if (hookId) { | ||
| await this.app.deleteHook({ | ||
| data: { | ||
| webhook_id: hookId, | ||
| sheet_slug: this.sheetId, | ||
| }, | ||
| }); | ||
| this._setHookID(null); | ||
| this._setSampleRow(null); | ||
| } | ||
| } catch (err) { | ||
| console.error("Deactivation Error:", err); | ||
| } | ||
| }, | ||
| async deploy() { | ||
| const sampleRow = this._getSampleRow(); | ||
| if (!sampleRow) { | ||
| console.log("No sample row data found to emit during deploy."); | ||
| } | ||
| // Sample already emitted during activation; skipping duplicate emission | ||
| }, | ||
|
Comment on lines
+96
to
+102
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can remove this block since you won't get any sampleRow data in deploy time |
||
| }, | ||
| methods: { | ||
| /** | ||
| * Retrieves the stored webhook ID from persistent storage | ||
| * @returns {string|null} The webhook ID or null if not set | ||
| */ | ||
| _getHookID() { | ||
| return this.db.get("hookId"); | ||
| }, | ||
| /** | ||
| * Stores the webhook ID in persistent storage | ||
| * @param {string|null} hookID - The webhook ID to store | ||
| */ | ||
| _setHookID(hookID) { | ||
| this.db.set("hookId", hookID); | ||
| }, | ||
| /** | ||
| * Retrieves the stored sample row data from persistent storage | ||
| * @returns {object|null} The sample row data or null if not set | ||
| */ | ||
| _getSampleRow() { | ||
| return this.db.get("sampleRow"); | ||
| }, | ||
| /** | ||
| * Stores sample row data in persistent storage | ||
| * @param {object|null} rowData - The sample row data to store | ||
| */ | ||
| _setSampleRow(rowData) { | ||
| this.db.set("sampleRow", rowData); | ||
| }, | ||
| }, | ||
| async run(event) { | ||
| const { body } = event; | ||
|
|
||
| if (!Array.isArray(body) || body.length === 0) { | ||
| console.error("Received webhook payload without row data"); | ||
| return; | ||
| } | ||
|
|
||
| for (const row of body) { | ||
| this.$emit(row, { | ||
| id: row.import_id || `${row.sheet_id}_${row.row_number}_${Date.now()}`, | ||
| summary: `New data imported to sheet ${row.sheet_name}`, | ||
| ts: Date.now(), | ||
| }); | ||
| } | ||
| }, | ||
| sampleEvents: [ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename this property to this would be the example of the content of the file: Then you can import the test event like this: |
||
| { | ||
| import_id: 79418895, | ||
| sheet_id: 55, | ||
| sheet_name: "Products", | ||
| row_number: 1, | ||
| row_data: { | ||
| "col1": "", | ||
| "col2": "", | ||
| "col3": "", | ||
| "col4": "", | ||
| "col5": "", | ||
| }, | ||
| total_rows: 10, | ||
| env_name: "default", | ||
| custom_fields: { | ||
| user_id: "default123" | ||
| }, | ||
| import_description: "This is a sample test import", | ||
| original_filename: "product_details.csv", | ||
| } | ||
| ], | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,55 +1,80 @@ | ||
| import { axios } from "@pipedream/platform"; | ||
| import constants from "./common/constants.mjs"; | ||
|
|
||
| export default { | ||
| type: "app", | ||
| app: "csvbox", | ||
| propDefinitions: { | ||
| sheetLicenseKey: { | ||
| sheetId: { | ||
| type: "string", | ||
| label: "Sheet License Key", | ||
| description: "The unique identifier for your CSVBox sheet. You can find it in **Sheets - Edit - Code Snippet - Sheet License Key**.", | ||
| }, | ||
| userId: { | ||
| type: "string", | ||
| label: "User ID", | ||
| description: "The unique identifier for the user. You can find it in the **Dashboard - Edit - Code Snippet**.", | ||
| optional: true, | ||
| }, | ||
| hasHeaders: { | ||
| type: "boolean", | ||
| label: "Has Headers", | ||
| description: "Whether the spreadsheet has headers.", | ||
| label: "Sheet", | ||
| description: "Select the sheet you want to receive data from", | ||
| optional: true, | ||
| async options() { | ||
| const { data } = await this.listSheets(); | ||
| return data.map((sheet) => ({ | ||
| label: sheet.name, | ||
| value: sheet.value, | ||
| })); | ||
| }, | ||
| }, | ||
| }, | ||
|
|
||
| methods: { | ||
| getUrl(path) { | ||
| return `https://api.csvbox.io/1.1${path}`; | ||
| _getAuthKeys() { | ||
| return this.$auth.api_key; | ||
| }, | ||
| _getSecretAuthKeys() { | ||
| return this.$auth.secret_api_key; | ||
| }, | ||
| getHeaders(headers) { | ||
| _getUrl(path) { | ||
| return `${constants.BASE_URL}${path}`; | ||
| }, | ||
| _getHeaders(headers) { | ||
| return { | ||
| "Content-Type": "application/json", | ||
| "x-csvbox-api-key": `${this.$auth.api_key}`, | ||
| "x-csvbox-secret-api-key": `${this.$auth.secret_api_key}`, | ||
| ...headers, | ||
| accept: "application/json", | ||
| "Content-Type": "application/json", | ||
| "x-csvbox-api-key": this._getAuthKeys(), | ||
| "x-csvbox-secret-api-key": this._getSecretAuthKeys(), | ||
| }; | ||
| }, | ||
| _makeRequest({ | ||
| $ = this, path, headers, ...args | ||
| } = {}) { | ||
| return axios($, { | ||
| debug: true, | ||
| url: this.getUrl(path), | ||
| headers: this.getHeaders(headers), | ||
|
|
||
| async _makeRequest({ $ = this, path, headers, ...otherConfig } = {}) { | ||
| const config = { | ||
| url: this._getUrl(path), | ||
| headers: this._getHeaders(headers), | ||
| returnFullResponse: true, | ||
| ...otherConfig, | ||
| }; | ||
| return axios($, config); | ||
| }, | ||
|
|
||
| async createHook({ data, ...args } = {}) { | ||
| return this._makeRequest({ | ||
| method: "POST", | ||
| path: "/register-webhook", | ||
| data, | ||
| ...args, | ||
| }); | ||
| }, | ||
| submitFile(args = {}) { | ||
|
|
||
| async deleteHook({ data, ...args } = {}) { | ||
| return this._makeRequest({ | ||
| method: "POST", | ||
| path: "/file", | ||
| method: "DELETE", | ||
| path: `/delete-webhook`, | ||
| data, | ||
| ...args, | ||
| }); | ||
| }, | ||
|
|
||
| async listSheets(args = {}) { | ||
| const res = await this._makeRequest({ | ||
| method: "GET", | ||
| path: "/list-sheets", | ||
| ...args, | ||
| }); | ||
| return res; | ||
| }, | ||
| }, | ||
| }; |
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.
Can you explain why are you removing this action component?