Skip to content

Commit

Permalink
[Components] twenty #11736
Browse files Browse the repository at this point in the history
Sources
 - New Record (Instant)

Actions
 - Create Update Delete Record
  • Loading branch information
luancazarine committed May 7, 2024
1 parent 6fcffc8 commit 68d1632
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { camelCaseToWords } from "../../common/utils.mjs";
import twenty from "../../twenty.app.mjs";
import { axios } from "@pipedream/platform";

export default {
key: "twenty-create-update-delete-record",
Expand All @@ -14,34 +14,107 @@ export default {
twenty,
"recordId",
],
},
recordData: {
propDefinition: [
twenty,
"recordData",
],
reloadProps: true,
},
actionType: {
propDefinition: [
twenty,
"actionType",
],
reloadProps: true,
},
},
async additionalProps() {
const props = {};
const recordId = this.recordId;
const actionType = this.actionType;

if (recordId && this.actionType) {
if ([
"delete",
"update",
].includes(actionType)) {
props.id = {
type: "string",
label: `${camelCaseToWords(recordId)} Id`,
description: `The Id of ${recordId}`,
options: async () => {
const {
components: { schemas }, tags,
} = await this.twenty.listRecords();
const index = Object.keys(schemas).findIndex((i) => i === this.recordId);
const { data } = await this.twenty.listRecordItems(tags[index + 1].name);
const response = data[tags[index + 1].name];
return response.map((item) => ({
label: item.name || item.title || item.id,
value: item.id,
}));
},
};
}

if ([
"create",
"update",
].includes(actionType)) {

const { components: { schemas } } = await this.twenty.listRecords();
const properties = schemas[recordId].properties;
const required = schemas[recordId].required || [];

for (const [
key,
value,
] of Object.entries(properties)) {
if (
(key != "id") &&
(key != "createdAt") &&
(key != "updatedAt") &&
(value.type) &&
(value.type != "object")
) {
props[key] = {
type: value["type"] === "array"
? "string[]"
: value["type"] === "number"
? "integer"
: value["type"],
label: camelCaseToWords(key),
description: value["description"],
optional: !(required.includes === key),
};
}
}
}
}
return props;
},
async run({ $ }) {
const actionType = this.actionType || "create"; // Default to create if not specified
const {
twenty,
id,
recordId,
actionType,
...data
} = this;

let response;

const {
components: { schemas }, tags,
} = await this.twenty.listRecords();
const index = Object.keys(schemas).findIndex((i) => i === this.recordId);

try {
response = await this.twenty.performAction({
actionType,
recordId: this.recordId,
recordData: this.recordData,
response = await twenty.performAction({
$,
id,
actionType: this.actionType,
recordName: tags[index + 1].name,
data,
});

let summaryMessage = `Successfully performed ${actionType} action`;
if (this.recordId) summaryMessage += ` on record with ID ${this.recordId}`;
$.export("$summary", summaryMessage);
$.export("$summary", `Successfully performed ${actionType} ${recordId} on record with ID: ${id || response.data[`${actionType}${recordId}`].id}`);

return response;
} catch (error) {
Expand Down
8 changes: 8 additions & 0 deletions components/twenty/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const camelCaseToWords = (s) => {
const result = s.replace(/([A-Z])/g, " $1");
return result.charAt(0).toUpperCase() + result.slice(1);
};

export const capitalizeFirstLetter = (string) => {
return string.charAt(0).toLowerCase() + string.slice(1);
};
6 changes: 5 additions & 1 deletion components/twenty/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/twenty",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream Twenty Components",
"main": "twenty.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,9 @@
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^1.6.5"
}
}

66 changes: 24 additions & 42 deletions components/twenty/sources/new-record-instant/new-record-instant.mjs
Original file line number Diff line number Diff line change
@@ -1,63 +1,45 @@
import twenty from "../../twenty.app.mjs";
import { axios } from "@pipedream/platform";
import sampleEmit from "./test-event.mjs";

export default {
key: "twenty-new-record-instant",
name: "New Record Instant",
name: "New Record (Instant)",
description: "Emit new event when a record is created, updated, or deleted.",
version: "0.0.{{ts}}",
version: "0.0.1",
type: "source",
dedupe: "unique",
props: {
twenty: {
type: "app",
app: "twenty",
},
http: {
type: "$.interface.http",
customResponse: true,
},
twenty,
http: "$.interface.http",
db: "$.service.db",
},
hooks: {
async deploy() {
// This source does not fetch historical data
},
async activate() {
// Logic to create a webhook subscription if supported by the app
const { data } = await this.twenty.createHook({
data: {
targetUrl: this.http.endpoint,
operation: "*.*",
},
});

this.db.set("webhookId", data.createWebhook.id);
},
async deactivate() {
// Logic to delete the webhook subscription if supported by the app
const webhookId = this.db.get("webhookId");
await this.twenty.deleteHook(webhookId);
},
},
async run(event) {
const {
actionType, recordId, recordData,
} = event.body;
const { body } = event;

try {
const result = await this.twenty.performAction({
actionType,
recordId,
recordData,
});

this.$emit(result, {
id: result.id || `${actionType}-${Date.now()}`,
summary: `${actionType.toUpperCase()} action performed`,
ts: Date.parse(result.createdAt || new Date()),
});
const eventType = body.eventType;
const eventName = eventType.split(".")[0];

this.http.respond({
status: 200,
body: "Success",
});
} catch (error) {
this.http.respond({
status: 500,
body: "Internal Server Error",
});
console.error(`Error processing ${actionType} action:`, error);
}
this.$emit(body, {
id: `${body.objectMetadata.id}-${body.eventDate}`,
summary: `New ${body.objectMetadata.nameSingular} ${eventName}d with Id: ${body.objectMetadata.id}.`,
ts: Date.parse(body.eventDate) || Date.now(),
});
},
sampleEmit,
};
61 changes: 61 additions & 0 deletions components/twenty/sources/new-record-instant/test-event.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export default {
"targetUrl": "http://webhook.url",
"eventType": "*.*",
"objectMetadata": {
"id": "12345678-1234-1234-1234-123456789012",
"nameSingular": "company"
},
"workspaceId": "12345678-1234-1234-1234-123456789012",
"webhookId": "12345678-1234-1234-1234-123456789012",
"eventDate": "2024-05-07T14:16:39.810Z",
"record": {
"id": "12345678-1234-1234-1234-123456789012",
"name": "company test",
"people": {
"edges": [],
"__typename": "personConnection"
},
"address": "",
"position": 1,
"createdAt": "2024-05-07T14:16:39.350276+00:00",
"employees": null,
"favorites": {
"edges": [],
"__typename": "favoriteConnection"
},
"updatedAt": "2024-05-07T14:16:39.350276+00:00",
"__typename": "company",
"domainName": "",
"attachments": {
"edges": [],
"__typename": "attachmentConnection"
},
"accountOwner": null,
"opportunities": {
"edges": [],
"__typename": "opportunityConnection"
},
"accountOwnerId": null,
"activityTargets": {
"edges": [],
"__typename": "activityTargetConnection"
},
"timelineActivities": {
"edges": [],
"__typename": "timelineActivityConnection"
},
"idealCustomerProfile": false,
"xLink": {
"url": "",
"label": ""
},
"linkedinLink": {
"url": "",
"label": ""
},
"annualRecurringRevenue": {
"amountMicros": null,
"currencyCode": ""
}
}
}
Loading

0 comments on commit 68d1632

Please sign in to comment.