Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# pieces-fireberry
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build pieces-fireberry` to build the library.
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@activepieces/piece-fireberry",
|
||||
"version": "0.0.5",
|
||||
"type": "commonjs",
|
||||
"main": "./src/index.js",
|
||||
"types": "./src/index.d.ts",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "pieces-fireberry",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/pieces/community/fireberry/src",
|
||||
"projectType": "library",
|
||||
"release": {
|
||||
"version": {
|
||||
"manifestRootsToUpdate": [
|
||||
"dist/{projectRoot}"
|
||||
],
|
||||
"currentVersionResolver": "git-tag",
|
||||
"fallbackCurrentVersionResolver": "disk"
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/js:tsc",
|
||||
"outputs": [
|
||||
"{options.outputPath}"
|
||||
],
|
||||
"options": {
|
||||
"outputPath": "dist/packages/pieces/community/fireberry",
|
||||
"tsConfig": "packages/pieces/community/fireberry/tsconfig.lib.json",
|
||||
"packageJson": "packages/pieces/community/fireberry/package.json",
|
||||
"main": "packages/pieces/community/fireberry/src/index.ts",
|
||||
"assets": [
|
||||
"packages/pieces/community/fireberry/*.md",
|
||||
{
|
||||
"input": "packages/pieces/community/fireberry/src/i18n",
|
||||
"output": "./src/i18n",
|
||||
"glob": "**/!(i18n.json)"
|
||||
}
|
||||
],
|
||||
"buildableProjectDepsInPackageJsonType": "dependencies",
|
||||
"updateBuildableProjectDepsInPackageJson": true
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build",
|
||||
"prebuild"
|
||||
]
|
||||
},
|
||||
"nx-release-publish": {
|
||||
"options": {
|
||||
"packageRoot": "dist/{projectRoot}"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": [
|
||||
"{options.outputFile}"
|
||||
]
|
||||
},
|
||||
"prebuild": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "packages/pieces/community/fireberry",
|
||||
"command": "bun install --no-save --silent"
|
||||
},
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Geben Sie Ihren Fireberry API Key ein. Sie können ihn aus Ihren Fireberry Account-Einstellungen generieren.",
|
||||
"Create Record": "Datensatz erstellen",
|
||||
"Update Record": "Datensatz aktualisieren",
|
||||
"Delete Records": "Datensätze löschen",
|
||||
"Find Records": "Datensätze finden",
|
||||
"Create a new record in Fireberry.": "Erstellen Sie einen neuen Rekord in Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Aktualisiere einen vorhandenen Eintrag in Fireberry.",
|
||||
"Delete records from Fireberry.": "Lösche Datensätze aus Fireberry.",
|
||||
"Search for records in Fireberry.": "Suche nach Datensätzen in Fireberry.",
|
||||
"Object Type": "Objekttyp",
|
||||
"Fields": "Felder",
|
||||
"Record": "Datensatz",
|
||||
"Fields to Update": "Zu aktualisierende Felder",
|
||||
"Records to Delete": "Zu löschende Datensätze",
|
||||
"Confirm Deletion": "Löschen bestätigen",
|
||||
"Search Query": "Suchanfrage",
|
||||
"Fields to Return": "Felder zum Zurückgeben",
|
||||
"Sort By Field": "Nach Feld sortieren",
|
||||
"Sort Order": "Sortierung",
|
||||
"Page Size": "Einträge pro Seite",
|
||||
"Page Number": "Seitennummer",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Aktivieren Sie diese Option, um zu bestätigen, dass Sie die ausgewählten Datensätze dauerhaft löschen möchten. Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Suchkriterien eingeben (z.B. \"accountname=John\" oder \"email contains @example.com\"). Leer lassen um alle Datensätze zu erhalten.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Systemname des zu sortierenden Feldes (z.B. \"createdon\", \"Accountname\")",
|
||||
"Number of records to return (max 50)": "Anzahl der zurückzugebenden Datensätze (max. 50)",
|
||||
"Page number to retrieve (max 10)": "Seitenzahl zum Abrufen (max 10)",
|
||||
"Descending (newest first)": "Absteigend (neueste zuerst)",
|
||||
"Ascending (oldest first)": "Aufsteigend (älteste zuerst)",
|
||||
"Record Created or Updated": "Datensatz erstellt oder aktualisiert",
|
||||
"Fires when a record is created or updated in Fireberry.": "Feuert ab, wenn ein Datensatz in Fireberry erstellt oder aktualisiert wird.",
|
||||
"Trigger Type": "Auslöse-Typ",
|
||||
"Lookback Period (minutes)": "Sehzeitraum (Minuten)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Wie weit zurück nach Datensätzen beim ersten Start gesucht werden soll (Standard: 60 Minuten)",
|
||||
"Created or Updated": "Erstellt oder aktualisiert",
|
||||
"Created Only": "Nur erstellt",
|
||||
"Updated Only": "Nur aktualisiert"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Introduzca su Clave API de Fireberry. Puede generarla desde la configuración de su cuenta Fireberry.",
|
||||
"Create Record": "Crear registro",
|
||||
"Update Record": "Actualizar registro",
|
||||
"Delete Records": "Borrar registros",
|
||||
"Find Records": "Buscar registros",
|
||||
"Create a new record in Fireberry.": "Crear un nuevo registro en Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Actualizar un registro existente en Fireberry.",
|
||||
"Delete records from Fireberry.": "Eliminar registros de Fireberry.",
|
||||
"Search for records in Fireberry.": "Buscar registros en Fireberry.",
|
||||
"Object Type": "Tipo de objeto",
|
||||
"Fields": "Campos",
|
||||
"Record": "Grabar",
|
||||
"Fields to Update": "Campos a actualizar",
|
||||
"Records to Delete": "Registros a eliminar",
|
||||
"Confirm Deletion": "Confirmar eliminación",
|
||||
"Search Query": "Buscar consulta",
|
||||
"Fields to Return": "Campos a devolver",
|
||||
"Sort By Field": "Ordenar por campo",
|
||||
"Sort Order": "Ordenar",
|
||||
"Page Size": "Tamaño de página",
|
||||
"Page Number": "Número de página",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Marque esta casilla para confirmar que desea eliminar permanentemente los registros seleccionados. Esta acción no se puede deshacer.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Introduzca criterios de búsqueda (por ejemplo, \"accountname=John\" o \"email contiene @example.com\"). Deje en blanco para obtener todos los registros.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Nombre del sistema del campo por el que ordenar (por ej., \"createdon\", \"nombre\")",
|
||||
"Number of records to return (max 50)": "Número de registros a devolver (máx. 50)",
|
||||
"Page number to retrieve (max 10)": "Número de página a recuperar (máx. 10)",
|
||||
"Descending (newest first)": "Descendente (más reciente primero)",
|
||||
"Ascending (oldest first)": "Ascendente (más antiguo primero)",
|
||||
"Record Created or Updated": "Registro Creado o Actualizado",
|
||||
"Fires when a record is created or updated in Fireberry.": "Dispara cuando un registro es creado o actualizado en Fireberry.",
|
||||
"Trigger Type": "Tipo de disparador",
|
||||
"Lookback Period (minutes)": "Periodo de búsqueda (minutos)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Qué tan lejos buscar registros en la primera ejecución (por defecto: 60 minutos)",
|
||||
"Created or Updated": "Creado o actualizado",
|
||||
"Created Only": "Sólo creado",
|
||||
"Updated Only": "Sólo Actualizado"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Entrez votre clé API Fireberry. Vous pouvez la générer à partir des paramètres de votre compte Fireberry.",
|
||||
"Create Record": "Créer un enregistrement",
|
||||
"Update Record": "Mettre à jour l'enregistrement",
|
||||
"Delete Records": "Supprimer les enregistrements",
|
||||
"Find Records": "Trouver des enregistrements",
|
||||
"Create a new record in Fireberry.": "Créer un nouvel enregistrement dans Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Mettre à jour un enregistrement existant dans Fireberry.",
|
||||
"Delete records from Fireberry.": "Supprimer les enregistrements de Fireberry.",
|
||||
"Search for records in Fireberry.": "Rechercher des enregistrements dans Fireberry.",
|
||||
"Object Type": "Type d'objet",
|
||||
"Fields": "Champs",
|
||||
"Record": "Enregistrements",
|
||||
"Fields to Update": "Champs à mettre à jour",
|
||||
"Records to Delete": "Enregistrements à supprimer",
|
||||
"Confirm Deletion": "Confirmer la suppression",
|
||||
"Search Query": "Requête de recherche",
|
||||
"Fields to Return": "Champs à retourner",
|
||||
"Sort By Field": "Trier par champ",
|
||||
"Sort Order": "Ordre de tri",
|
||||
"Page Size": "Nombre d'élément",
|
||||
"Page Number": "Numéro de page",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Cochez cette case pour confirmer que vous souhaitez supprimer définitivement les enregistrements sélectionnés. Cette action ne peut pas être annulée.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Entrez les critères de recherche (par exemple, \"accountname=John\" ou \"email contains @example.com\"). Laissez vide pour obtenir tous les enregistrements.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Nom du système du champ à trier (par exemple, \"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Nombre d'enregistrements à retourner (max 50)",
|
||||
"Page number to retrieve (max 10)": "Numéro de page à récupérer (max 10)",
|
||||
"Descending (newest first)": "Décroissant (plus récent en premier)",
|
||||
"Ascending (oldest first)": "Ascendant (plus ancien en premier)",
|
||||
"Record Created or Updated": "Enregistrement créé ou mis à jour",
|
||||
"Fires when a record is created or updated in Fireberry.": "Se déclenche lorsqu'un enregistrement est créé ou mis à jour dans Fireberry.",
|
||||
"Trigger Type": "Type de déclencheur",
|
||||
"Lookback Period (minutes)": "Période de retour (minutes)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Jusqu'à quel point il faut chercher les enregistrements lors de la première exécution (par défaut: 60 minutes)",
|
||||
"Created or Updated": "Créé ou mis à jour",
|
||||
"Created Only": "Créé uniquement",
|
||||
"Updated Only": "Mis à jour uniquement"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Fireberry API キーを入力します。Fireberry アカウントの設定から生成できます。",
|
||||
"Create Record": "レコードを作成",
|
||||
"Update Record": "更新記録",
|
||||
"Delete Records": "レコードを削除",
|
||||
"Find Records": "レコードを検索",
|
||||
"Create a new record in Fireberry.": "Fireberryで新しいレコードを作成します。",
|
||||
"Update an existing record in Fireberry.": "Fireberryで既存のレコードを更新します。",
|
||||
"Delete records from Fireberry.": "Fireberryからレコードを削除する。",
|
||||
"Search for records in Fireberry.": "Fireberryでレコードを検索します。",
|
||||
"Object Type": "オブジェクトの種類",
|
||||
"Fields": "フィールド",
|
||||
"Record": "レコード",
|
||||
"Fields to Update": "更新するフィールド",
|
||||
"Records to Delete": "削除するレコード",
|
||||
"Confirm Deletion": "削除の確認",
|
||||
"Search Query": "検索クエリ",
|
||||
"Fields to Return": "Fields to Return",
|
||||
"Sort By Field": "フィールドでソート",
|
||||
"Sort Order": "並び順",
|
||||
"Page Size": "ページサイズ",
|
||||
"Page Number": "ページ番号",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "選択したレコードを完全に削除するかどうかを確認するには、このチェックボックスをオンにします。この操作は元に戻せません。",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "検索条件を入力してください(例:\"accountname=John\" または \"email contains @example.com\")。すべてのレコードを取得するには空のままにしてください。",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "システム名でソートする項目(例:\"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Number of records to return (max 50)",
|
||||
"Page number to retrieve (max 10)": "取得するページ番号(最大10)",
|
||||
"Descending (newest first)": "降順",
|
||||
"Ascending (oldest first)": "昇順 (古い順)",
|
||||
"Record Created or Updated": "作成または更新されたレコード",
|
||||
"Fires when a record is created or updated in Fireberry.": "Fireberryでレコードが作成または更新されたときに発火します。",
|
||||
"Trigger Type": "トリガータイプ",
|
||||
"Lookback Period (minutes)": "ルックバック期間 (分)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "最初の実行時にレコードを探すまでの距離(デフォルト:60分)",
|
||||
"Created or Updated": "作成または更新",
|
||||
"Created Only": "作成者のみ",
|
||||
"Updated Only": "更新のみ"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Voer uw Fireberry API-sleutel in. U kunt deze genereren via uw Fireberry account instellingen.",
|
||||
"Create Record": "Record Maken",
|
||||
"Update Record": "Update Record",
|
||||
"Delete Records": "Records verwijderen",
|
||||
"Find Records": "Records zoeken",
|
||||
"Create a new record in Fireberry.": "Maak een nieuw record in Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Werk een bestaand record bij in Fireberry.",
|
||||
"Delete records from Fireberry.": "Verwijder records van Fireberry.",
|
||||
"Search for records in Fireberry.": "Zoek naar records in Fireberry.",
|
||||
"Object Type": "Object type",
|
||||
"Fields": "Velden",
|
||||
"Record": "Opnemen",
|
||||
"Fields to Update": "Velden om te updaten",
|
||||
"Records to Delete": "Te verwijderen records",
|
||||
"Confirm Deletion": "Verwijdering bevestigen",
|
||||
"Search Query": "Zoek query",
|
||||
"Fields to Return": "Velden om te retourneren",
|
||||
"Sort By Field": "Sorteren op veld",
|
||||
"Sort Order": "Sorteren bestelling",
|
||||
"Page Size": "Paginagrootte",
|
||||
"Page Number": "Pagina Nummer",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Vink dit vakje aan om te bevestigen dat u de geselecteerde records permanent wilt verwijderen. Deze actie kan niet ongedaan worden gemaakt.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Voer zoekcriteria in (bijv. \"accountname=John\" of \"e-mail bevat @example.com\"). Laat leeg om alle records te krijgen.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Systeem naam van het te sorteren veld (bijv. \"aangemaakt\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Aantal terugkerende records (max 50)",
|
||||
"Page number to retrieve (max 10)": "Paginanummer op te halen (max 10)",
|
||||
"Descending (newest first)": "Aflopend (nieuwste eerst)",
|
||||
"Ascending (oldest first)": "Oplopend (oudste eerst)",
|
||||
"Record Created or Updated": "Record gemaakt of bijgewerkt",
|
||||
"Fires when a record is created or updated in Fireberry.": "Vuurt wanneer een record wordt aangemaakt of bijgewerkt in Fireberry.",
|
||||
"Trigger Type": "Trigger type",
|
||||
"Lookback Period (minutes)": "Zoekperiode (minuten)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Hoe ver terug te zoeken naar records bij eerste uitvoering (standaard: 60 minuten)",
|
||||
"Created or Updated": "Gemaakt of bijgewerkt",
|
||||
"Created Only": "Alleen gemaakt",
|
||||
"Updated Only": "Alleen bijgewerkt"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Digite sua chave de API do Fireberry. Você pode gerá-la a partir das configurações da sua conta Fireberry.",
|
||||
"Create Record": "Criar Registro",
|
||||
"Update Record": "Atualizar Registro",
|
||||
"Delete Records": "Excluir registros",
|
||||
"Find Records": "Encontrar registros",
|
||||
"Create a new record in Fireberry.": "Criar um novo registro em Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Atualizar um registro existente no Fireberry.",
|
||||
"Delete records from Fireberry.": "Excluir registros da Fireberry.",
|
||||
"Search for records in Fireberry.": "Procurar por registros na Fireberry.",
|
||||
"Object Type": "Tipo de objeto",
|
||||
"Fields": "campos",
|
||||
"Record": "Gravar",
|
||||
"Fields to Update": "Campos para Atualização",
|
||||
"Records to Delete": "Registros para Excluir",
|
||||
"Confirm Deletion": "Confirmar Exclusão",
|
||||
"Search Query": "Consulta de Pesquisa",
|
||||
"Fields to Return": "Campos para Devolver",
|
||||
"Sort By Field": "Ordenar por Campo",
|
||||
"Sort Order": "Ordem de classificação",
|
||||
"Page Size": "Tamanho da página",
|
||||
"Page Number": "Número da página",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Marque esta caixa para confirmar que deseja apagar permanentemente os registros selecionados. Esta ação não pode ser desfeita.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Digite critérios de pesquisa (por exemplo, \"accountname=John\" ou \"email contains @example.com\"). Deixe em branco para obter todos os registros.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Nome do sistema do campo para ordenar (por exemplo, \"criado\", \"conta\")",
|
||||
"Number of records to return (max 50)": "Número de registros a retornar (máx. 50)",
|
||||
"Page number to retrieve (max 10)": "Número de página a ser recuperada (máx. 10)",
|
||||
"Descending (newest first)": "Descendente (mais recente primeiro)",
|
||||
"Ascending (oldest first)": "Crescente (mais antigos primeiro)",
|
||||
"Record Created or Updated": "Registro Criado ou Atualizado",
|
||||
"Fires when a record is created or updated in Fireberry.": "Atira quando um registro é criado ou atualizado no Fireberry.",
|
||||
"Trigger Type": "Tipo de gatilho",
|
||||
"Lookback Period (minutes)": "Período de Lookback (minutos)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Quão longe de procurar registros na primeira execução (padrão: 60 minutos)",
|
||||
"Created or Updated": "Criado ou Atualizado",
|
||||
"Created Only": "Criado Apenas",
|
||||
"Updated Only": "Somente Atualizado"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"Fireberry": "Огненная ягода",
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Введите ваш API ключ Fireberry. Вы можете сгенерировать его в настройках вашего аккаунта Fireberry.",
|
||||
"Create Record": "Создать запись",
|
||||
"Update Record": "Обновить запись",
|
||||
"Delete Records": "Удалить записи",
|
||||
"Find Records": "Найти записи",
|
||||
"Create a new record in Fireberry.": "Создать новую запись в Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Обновить существующую запись в Fireberry.",
|
||||
"Delete records from Fireberry.": "Удалить записи из Fireberry.",
|
||||
"Search for records in Fireberry.": "Поиск записей в Fireberry.",
|
||||
"Object Type": "Тип объекта",
|
||||
"Fields": "Поля",
|
||||
"Record": "Запись",
|
||||
"Fields to Update": "Поля для обновления",
|
||||
"Records to Delete": "Записи для удаления",
|
||||
"Confirm Deletion": "Подтвердите удаление",
|
||||
"Search Query": "Поисковый запрос",
|
||||
"Fields to Return": "Поля для возврата",
|
||||
"Sort By Field": "Сортировать по полю",
|
||||
"Sort Order": "Порядок сортировки",
|
||||
"Page Size": "Размер страницы",
|
||||
"Page Number": "Номер страницы",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Установите этот флажок, чтобы подтвердить, что вы хотите удалить выбранные записи. Это действие не может быть отменено.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Введите критерии поиска (например, \"accountname=John\" или \"email contains @example.com\"). Оставьте пустым, чтобы получить все записи.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "Системное имя поля для сортировки (например, \"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Количество возвращаемых записей (макс. 50)",
|
||||
"Page number to retrieve (max 10)": "Номер страницы для получения (не более 10)",
|
||||
"Descending (newest first)": "По убыванию (сначала новые)",
|
||||
"Ascending (oldest first)": "По возрастанию (сначала старые)",
|
||||
"Record Created or Updated": "Запись создана или обновлена",
|
||||
"Fires when a record is created or updated in Fireberry.": "Вызывает, когда запись создается или обновляется в Fireberry.",
|
||||
"Trigger Type": "Тип триггера",
|
||||
"Lookback Period (minutes)": "Период поиска (минуты)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "Как далеко назад искать записи при первом запуске (по умолчанию: 60 минут)",
|
||||
"Created or Updated": "Создано или обновлено",
|
||||
"Created Only": "Только созданные",
|
||||
"Updated Only": "Только обновленные"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Enter your Fireberry API Key. You can generate it from your Fireberry account settings.",
|
||||
"Create Record": "Create Record",
|
||||
"Update Record": "Update Record",
|
||||
"Delete Records": "Delete Records",
|
||||
"Find Records": "Find Records",
|
||||
"Create a new record in Fireberry.": "Create a new record in Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Update an existing record in Fireberry.",
|
||||
"Delete records from Fireberry.": "Delete records from Fireberry.",
|
||||
"Search for records in Fireberry.": "Search for records in Fireberry.",
|
||||
"Object Type": "Object Type",
|
||||
"Fields": "Fields",
|
||||
"Record": "Record",
|
||||
"Fields to Update": "Fields to Update",
|
||||
"Records to Delete": "Records to Delete",
|
||||
"Confirm Deletion": "Confirm Deletion",
|
||||
"Search Query": "Search Query",
|
||||
"Fields to Return": "Fields to Return",
|
||||
"Sort By Field": "Sort By Field",
|
||||
"Sort Order": "Sort Order",
|
||||
"Page Size": "Page Size",
|
||||
"Page Number": "Page Number",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "System name of field to sort by (e.g., \"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Number of records to return (max 50)",
|
||||
"Page number to retrieve (max 10)": "Page number to retrieve (max 10)",
|
||||
"Descending (newest first)": "Descending (newest first)",
|
||||
"Ascending (oldest first)": "Ascending (oldest first)",
|
||||
"Record Created or Updated": "Record Created or Updated",
|
||||
"Fires when a record is created or updated in Fireberry.": "Fires when a record is created or updated in Fireberry.",
|
||||
"Trigger Type": "Trigger Type",
|
||||
"Lookback Period (minutes)": "Lookback Period (minutes)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "How far back to look for records on first run (default: 60 minutes)",
|
||||
"Created or Updated": "Created or Updated",
|
||||
"Created Only": "Created Only",
|
||||
"Updated Only": "Updated Only"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"Fireberry": "Fireberry",
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Enter your Fireberry API Key. You can generate it from your Fireberry account settings.",
|
||||
"Create Record": "Create Record",
|
||||
"Update Record": "Update Record",
|
||||
"Delete Records": "Delete Records",
|
||||
"Find Records": "Find Records",
|
||||
"Create a new record in Fireberry.": "Create a new record in Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Update an existing record in Fireberry.",
|
||||
"Delete records from Fireberry.": "Delete records from Fireberry.",
|
||||
"Search for records in Fireberry.": "Search for records in Fireberry.",
|
||||
"Object Type": "Object Type",
|
||||
"Fields": "Fields",
|
||||
"Record": "Record",
|
||||
"Fields to Update": "Fields to Update",
|
||||
"Records to Delete": "Records to Delete",
|
||||
"Confirm Deletion": "Confirm Deletion",
|
||||
"Search Query": "Search Query",
|
||||
"Fields to Return": "Fields to Return",
|
||||
"Sort By Field": "Sort By Field",
|
||||
"Sort Order": "Sort Order",
|
||||
"Page Size": "Phân trang",
|
||||
"Page Number": "Page Number",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "System name of field to sort by (e.g., \"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Number of records to return (max 50)",
|
||||
"Page number to retrieve (max 10)": "Page number to retrieve (max 10)",
|
||||
"Descending (newest first)": "Descending (newest first)",
|
||||
"Ascending (oldest first)": "Ascending (oldest first)",
|
||||
"Record Created or Updated": "Record Created or Updated",
|
||||
"Fires when a record is created or updated in Fireberry.": "Fires when a record is created or updated in Fireberry.",
|
||||
"Trigger Type": "Trigger Type",
|
||||
"Lookback Period (minutes)": "Lookback Period (minutes)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "How far back to look for records on first run (default: 60 minutes)",
|
||||
"Created or Updated": "Created or Updated",
|
||||
"Created Only": "Created Only",
|
||||
"Updated Only": "Updated Only"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Enter your Fireberry API Key. You can generate it from your Fireberry account settings.": "Enter your Fireberry API Key. You can generate it from your Fireberry account settings.",
|
||||
"Create Record": "Create Record",
|
||||
"Update Record": "Update Record",
|
||||
"Delete Records": "删除记录",
|
||||
"Find Records": "Find Records",
|
||||
"Create a new record in Fireberry.": "Create a new record in Fireberry.",
|
||||
"Update an existing record in Fireberry.": "Update an existing record in Fireberry.",
|
||||
"Delete records from Fireberry.": "Delete records from Fireberry.",
|
||||
"Search for records in Fireberry.": "Search for records in Fireberry.",
|
||||
"Object Type": "Object Type",
|
||||
"Fields": "Fields",
|
||||
"Record": "Record",
|
||||
"Fields to Update": "Fields to Update",
|
||||
"Records to Delete": "Records to Delete",
|
||||
"Confirm Deletion": "确认删除",
|
||||
"Search Query": "Search Query",
|
||||
"Fields to Return": "Fields to Return",
|
||||
"Sort By Field": "Sort By Field",
|
||||
"Sort Order": "Sort Order",
|
||||
"Page Size": "Page Size",
|
||||
"Page Number": "Page Number",
|
||||
"Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.": "Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.",
|
||||
"Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.": "Enter search criteria (e.g., \"accountname=John\" or \"email contains @example.com\"). Leave empty to get all records.",
|
||||
"System name of field to sort by (e.g., \"createdon\", \"accountname\")": "System name of field to sort by (e.g., \"createdon\", \"accountname\")",
|
||||
"Number of records to return (max 50)": "Number of records to return (max 50)",
|
||||
"Page number to retrieve (max 10)": "Page number to retrieve (max 10)",
|
||||
"Descending (newest first)": "Descending (newest first)",
|
||||
"Ascending (oldest first)": "Ascending (oldest first)",
|
||||
"Record Created or Updated": "Record Created or Updated",
|
||||
"Fires when a record is created or updated in Fireberry.": "Fires when a record is created or updated in Fireberry.",
|
||||
"Trigger Type": "Trigger Type",
|
||||
"Lookback Period (minutes)": "Lookback Period (minutes)",
|
||||
"How far back to look for records on first run (default: 60 minutes)": "How far back to look for records on first run (default: 60 minutes)",
|
||||
"Created or Updated": "Created or Updated",
|
||||
"Created Only": "Created Only",
|
||||
"Updated Only": "Updated Only"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { createPiece, PieceAuth } from "@activepieces/pieces-framework";
|
||||
import { PieceCategory } from "@activepieces/shared";
|
||||
import { createRecordAction } from "./lib/actions/create-record.action";
|
||||
import { updateRecordAction } from "./lib/actions/update-record.action";
|
||||
import { deleteRecordAction } from "./lib/actions/delete-record.action";
|
||||
import { findRecordAction } from "./lib/actions/find-record.action";
|
||||
import { recordCreatedOrUpdatedTrigger } from "./lib/triggers/record-created-updated.trigger";
|
||||
|
||||
export const fireberryAuth = PieceAuth.SecretText({
|
||||
displayName: 'API Key',
|
||||
description: 'Enter your Fireberry API Key. You can generate it from your Fireberry account settings.',
|
||||
required: true,
|
||||
});
|
||||
|
||||
export const fireberry = createPiece({
|
||||
displayName: "Fireberry",
|
||||
auth: fireberryAuth,
|
||||
minimumSupportedRelease: '0.36.1',
|
||||
logoUrl: "https://cdn.activepieces.com/pieces/fireberry.png",
|
||||
authors: ["sparkybug", "onyedikachi-david"],
|
||||
categories: [PieceCategory.SALES_AND_CRM],
|
||||
actions: [
|
||||
createRecordAction,
|
||||
updateRecordAction,
|
||||
deleteRecordAction,
|
||||
findRecordAction,
|
||||
],
|
||||
triggers: [
|
||||
recordCreatedOrUpdatedTrigger,
|
||||
],
|
||||
});
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { fireberryAuth } from '../../index';
|
||||
import { objectTypeDropdown, objectFields } from '../common/props';
|
||||
import { FireberryClient } from '../common/client';
|
||||
|
||||
export const createRecordAction = createAction({
|
||||
name: 'create_record',
|
||||
displayName: 'Create Record',
|
||||
description: 'Create a new record in Fireberry.',
|
||||
auth: fireberryAuth,
|
||||
props: {
|
||||
objectType: objectTypeDropdown,
|
||||
fields: objectFields,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType, fields } = propsValue;
|
||||
|
||||
const fieldsObj = typeof fields === 'string' ? JSON.parse(fields) : fields;
|
||||
|
||||
if (typeof fieldsObj !== 'object' || fieldsObj === null) {
|
||||
throw new Error('Fields must be an object');
|
||||
}
|
||||
|
||||
return await client.batchCreate(objectType as string, [fieldsObj]);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { fireberryAuth } from '../../index';
|
||||
import { objectTypeDropdown } from '../common/props';
|
||||
import { FireberryClient } from '../common/client';
|
||||
|
||||
const recordsToDeleteDropdown = Property.MultiSelectDropdown({
|
||||
auth: fireberryAuth,
|
||||
displayName: 'Records to Delete',
|
||||
required: true,
|
||||
refreshers: ['objectType'],
|
||||
options: async ({ auth, objectType }) => {
|
||||
if (!auth || !objectType) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Select object type first',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const objectTypeStr = typeof objectType === 'string' ? objectType : (objectType as { value: string })?.value;
|
||||
const client = new FireberryClient(auth);
|
||||
|
||||
const response = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
Records: Array<Record<string, any>>;
|
||||
PrimaryField: string;
|
||||
PrimaryKey: string;
|
||||
Total_Records: number;
|
||||
}
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/api/record/${objectTypeStr}?$top=100`,
|
||||
});
|
||||
|
||||
if (!response.data?.Records || !Array.isArray(response.data.Records)) {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [],
|
||||
placeholder: response.data?.Total_Records === 0 ? 'No records found' : 'Error loading records',
|
||||
};
|
||||
}
|
||||
|
||||
const primaryField = response.data.PrimaryField;
|
||||
const primaryKey = response.data.PrimaryKey;
|
||||
|
||||
const options = response.data.Records.map((record: any) => {
|
||||
const displayName = record[primaryField] ||
|
||||
record.name || record.title || record.subject ||
|
||||
record.firstname || record.lastname || record.email ||
|
||||
record.accountname || record.contactname ||
|
||||
`Record ${record[primaryKey]?.substring(0, 8) || 'Unknown'}`;
|
||||
|
||||
return {
|
||||
label: displayName,
|
||||
value: record[primaryKey],
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: options.slice(0, 100),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [],
|
||||
placeholder: 'Error loading records',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteRecordAction = createAction({
|
||||
name: 'delete_record',
|
||||
displayName: 'Delete Records',
|
||||
description: 'Delete records from Fireberry.',
|
||||
auth: fireberryAuth,
|
||||
props: {
|
||||
objectType: objectTypeDropdown,
|
||||
recordIds: recordsToDeleteDropdown,
|
||||
confirmDeletion: Property.Checkbox({
|
||||
displayName: 'Confirm Deletion',
|
||||
required: true,
|
||||
description: 'Check this box to confirm you want to permanently delete the selected records. This action cannot be undone.',
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType, recordIds, confirmDeletion } = propsValue;
|
||||
|
||||
if (!confirmDeletion) {
|
||||
throw new Error('You must confirm deletion by checking the confirmation box');
|
||||
}
|
||||
|
||||
if (!recordIds || !Array.isArray(recordIds) || recordIds.length === 0) {
|
||||
throw new Error('At least one record must be selected for deletion');
|
||||
}
|
||||
|
||||
if (recordIds.length > 20) {
|
||||
throw new Error('Maximum 20 records can be deleted at once');
|
||||
}
|
||||
|
||||
const result = await client.batchDelete(objectType as string, recordIds);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
deletedCount: recordIds.length,
|
||||
recordIds: recordIds,
|
||||
message: `Successfully deleted ${recordIds.length} record(s)`,
|
||||
apiResponse: result,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,177 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { fireberryAuth } from '../../index';
|
||||
import { objectTypeDropdown } from '../common/props';
|
||||
import { FireberryClient } from '../common/client';
|
||||
|
||||
const fieldsToReturn = Property.DynamicProperties({
|
||||
displayName: 'Fields to Return',
|
||||
refreshers: ['objectType'],
|
||||
required: false,
|
||||
auth: fireberryAuth,
|
||||
props: async ({ auth, objectType }) => {
|
||||
if (!auth || !objectType) return {};
|
||||
|
||||
const objectTypeStr = typeof objectType === 'string' ? objectType : (objectType as { value: string })?.value;
|
||||
const client = new FireberryClient(auth);
|
||||
|
||||
try {
|
||||
const metadata = await client.getObjectFieldsMetadata(objectTypeStr);
|
||||
const props: Record<string, any> = {};
|
||||
|
||||
for (const field of metadata.data) {
|
||||
const systemFields = ['createdby', 'modifiedby', 'deletedby'];
|
||||
if (field.fieldName.endsWith('id') && !field.label) {
|
||||
continue;
|
||||
}
|
||||
if (systemFields.includes(field.fieldName.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
props[field.fieldName] = Property.Checkbox({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: false,
|
||||
description: `Include ${field.label || field.fieldName} in search results`,
|
||||
});
|
||||
}
|
||||
|
||||
return props;
|
||||
} catch (error) {
|
||||
console.error('Error fetching fields for selection:', error);
|
||||
return {};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const findRecordAction = createAction({
|
||||
name: 'find_record',
|
||||
displayName: 'Find Records',
|
||||
description: 'Search for records in Fireberry.',
|
||||
auth: fireberryAuth,
|
||||
props: {
|
||||
objectType: objectTypeDropdown,
|
||||
searchQuery: Property.LongText({
|
||||
displayName: 'Search Query',
|
||||
required: false,
|
||||
description: 'Enter search criteria (e.g., "accountname=John" or "email contains @example.com"). Leave empty to get all records.',
|
||||
}),
|
||||
fieldsToReturn: fieldsToReturn,
|
||||
sortBy: Property.ShortText({
|
||||
displayName: 'Sort By Field',
|
||||
required: false,
|
||||
description: 'System name of field to sort by (e.g., "createdon", "accountname")',
|
||||
}),
|
||||
sortOrder: Property.StaticDropdown({
|
||||
displayName: 'Sort Order',
|
||||
required: false,
|
||||
defaultValue: 'desc',
|
||||
options: {
|
||||
disabled: false,
|
||||
options: [
|
||||
{ label: 'Descending (newest first)', value: 'desc' },
|
||||
{ label: 'Ascending (oldest first)', value: 'asc' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
pageSize: Property.Number({
|
||||
displayName: 'Page Size',
|
||||
required: false,
|
||||
defaultValue: 25,
|
||||
description: 'Number of records to return (max 50)',
|
||||
}),
|
||||
pageNumber: Property.Number({
|
||||
displayName: 'Page Number',
|
||||
required: false,
|
||||
defaultValue: 1,
|
||||
description: 'Page number to retrieve (max 10)',
|
||||
}),
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType, searchQuery, fieldsToReturn, sortBy, sortOrder, pageSize, pageNumber } = propsValue;
|
||||
|
||||
const selectedFields: string[] = [];
|
||||
if (fieldsToReturn && typeof fieldsToReturn === 'object') {
|
||||
for (const [fieldName, isSelected] of Object.entries(fieldsToReturn)) {
|
||||
if (isSelected === true) {
|
||||
selectedFields.push(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const objectsMetadata = await client.getObjectsMetadata();
|
||||
const targetObject = objectsMetadata.data.find(obj => obj.systemName === objectType);
|
||||
|
||||
if (!targetObject) {
|
||||
throw new Error(`Object type '${objectType}' not found`);
|
||||
}
|
||||
|
||||
const queryBody: Record<string, any> = {
|
||||
objecttype: parseInt(targetObject.objectType),
|
||||
};
|
||||
|
||||
if (selectedFields.length > 0) {
|
||||
queryBody['fields'] = selectedFields.join(',');
|
||||
}
|
||||
|
||||
if (searchQuery && searchQuery.trim()) {
|
||||
queryBody['query'] = searchQuery.trim();
|
||||
}
|
||||
|
||||
if (sortBy && sortBy.trim()) {
|
||||
queryBody['sort_by'] = sortBy.trim();
|
||||
queryBody['sort_type'] = sortOrder || 'desc';
|
||||
}
|
||||
|
||||
if (pageSize) {
|
||||
queryBody['page_size'] = Math.min(Math.max(1, pageSize), 50);
|
||||
}
|
||||
if (pageNumber) {
|
||||
queryBody['page_number'] = Math.min(Math.max(1, pageNumber), 10);
|
||||
}
|
||||
|
||||
const response = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
ObjectName: string;
|
||||
SystemName: string;
|
||||
ObjectType: number;
|
||||
PrimaryKey: string;
|
||||
PrimaryField: string;
|
||||
PageNum: number;
|
||||
SortBy: string;
|
||||
SortBy_Desc: boolean;
|
||||
IsLastPage: boolean;
|
||||
Columns: Array<Record<string, any>>;
|
||||
Data: Array<Record<string, any>>;
|
||||
};
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: '/api/query',
|
||||
body: queryBody,
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error('Query failed');
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
query: queryBody,
|
||||
results: {
|
||||
objectName: response.data.ObjectName,
|
||||
systemName: response.data.SystemName,
|
||||
objectType: response.data.ObjectType,
|
||||
pageNumber: response.data.PageNum,
|
||||
sortBy: response.data.SortBy,
|
||||
sortDescending: response.data.SortBy_Desc,
|
||||
isLastPage: response.data.IsLastPage,
|
||||
primaryKey: response.data.PrimaryKey,
|
||||
primaryField: response.data.PrimaryField,
|
||||
columns: response.data.Columns,
|
||||
records: response.data.Data,
|
||||
recordCount: response.data.Data.length,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,269 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { fireberryAuth } from '../../index';
|
||||
import { objectTypeDropdown } from '../common/props';
|
||||
import { FireberryClient } from '../common/client';
|
||||
|
||||
const recordDropdown = Property.Dropdown({
|
||||
auth: fireberryAuth,
|
||||
displayName: 'Record',
|
||||
required: true,
|
||||
refreshers: ['objectType'],
|
||||
options: async ({ auth, objectType }) => {
|
||||
if (!auth || !objectType) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Select object type first',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const objectTypeStr = typeof objectType === 'string' ? objectType : (objectType as { value: string })?.value;
|
||||
const client = new FireberryClient(auth);
|
||||
|
||||
const response = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
Records: Array<Record<string, any>>;
|
||||
PrimaryField: string;
|
||||
PrimaryKey: string;
|
||||
Total_Records: number;
|
||||
}
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/api/record/${objectTypeStr}?$top=50`,
|
||||
});
|
||||
|
||||
if (!response.data?.Records || !Array.isArray(response.data.Records)) {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [],
|
||||
placeholder: response.data?.Total_Records === 0 ? 'No records found' : 'Error loading records',
|
||||
};
|
||||
}
|
||||
|
||||
const primaryField = response.data.PrimaryField;
|
||||
const primaryKey = response.data.PrimaryKey;
|
||||
|
||||
const options = response.data.Records.map((record: any) => {
|
||||
const displayName = record[primaryField] ||
|
||||
record.name || record.title || record.subject ||
|
||||
record.firstname || record.lastname || record.email ||
|
||||
record.accountname || record.contactname ||
|
||||
`Record ${record[primaryKey]?.substring(0, 8) || 'Unknown'}`;
|
||||
|
||||
return {
|
||||
label: displayName,
|
||||
value: record[primaryKey],
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: options.slice(0, 50),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [],
|
||||
placeholder: 'Error loading records',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const updateFields = Property.DynamicProperties({
|
||||
displayName: 'Fields to Update',
|
||||
refreshers: ['objectType'],
|
||||
required: true,
|
||||
auth: fireberryAuth,
|
||||
props: async ({ auth, objectType }) => {
|
||||
if (!auth || !objectType) return {};
|
||||
|
||||
const objectTypeStr = typeof objectType === 'string' ? objectType : (objectType as { value: string })?.value;
|
||||
const client = new FireberryClient(auth);
|
||||
|
||||
try {
|
||||
const metadata = await client.getObjectFieldsMetadata(objectTypeStr);
|
||||
const props: Record<string, any> = {};
|
||||
|
||||
const fieldTypeMap: Record<string, string> = {
|
||||
'a1e7ed6f-5083-477b-b44c-9943a6181359': 'text',
|
||||
'ce972d02-5013-46d4-9d1d-f09df1ac346a': 'datetime',
|
||||
'6a34bfe3-fece-4da1-9136-a7b1e5ae3319': 'number',
|
||||
'a8fcdf65-91bc-46fd-82f6-1234758345a1': 'lookup',
|
||||
'b4919f2e-2996-48e4-a03c-ba39fb64386c': 'picklist',
|
||||
'80108f9d-1e75-40fa-9fa9-02be4ddc1da1': 'longtext',
|
||||
};
|
||||
|
||||
const picklistCache: Record<string, any> = {};
|
||||
const picklistFields = metadata.data.filter(field =>
|
||||
fieldTypeMap[field.systemFieldTypeId] === 'picklist'
|
||||
);
|
||||
|
||||
for (const field of picklistFields) {
|
||||
const largeLists = ['objecttypecode', 'resultcode'];
|
||||
if (!largeLists.includes(field.fieldName.toLowerCase())) {
|
||||
try {
|
||||
const picklistData = await client.getPicklistValues(objectTypeStr, field.fieldName);
|
||||
if (picklistData.data?.values && Array.isArray(picklistData.data.values)) {
|
||||
picklistCache[field.fieldName] = picklistData.data.values;
|
||||
}
|
||||
} catch (error) {
|
||||
picklistCache[field.fieldName] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const field of metadata.data) {
|
||||
const systemFields = ['createdby', 'modifiedby', 'deletedby', 'createdon', 'modifiedon', 'deletedon'];
|
||||
if (field.fieldName.endsWith('id') && !field.label) {
|
||||
continue;
|
||||
}
|
||||
if (systemFields.includes(field.fieldName.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fieldType = fieldTypeMap[field.systemFieldTypeId] || 'text';
|
||||
const isRequired = false;
|
||||
|
||||
switch (fieldType) {
|
||||
case 'text':
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Leave empty to keep current value',
|
||||
});
|
||||
break;
|
||||
case 'number':
|
||||
props[field.fieldName] = Property.Number({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Leave empty to keep current value',
|
||||
});
|
||||
break;
|
||||
case 'datetime':
|
||||
props[field.fieldName] = Property.DateTime({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Leave empty to keep current value',
|
||||
});
|
||||
break;
|
||||
case 'picklist': {
|
||||
const largeLists = ['objecttypecode', 'resultcode'];
|
||||
if (largeLists.includes(field.fieldName.toLowerCase())) {
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Enter numeric value (leave empty to keep current)',
|
||||
});
|
||||
} else {
|
||||
const values = picklistCache[field.fieldName] || [];
|
||||
if (values.length > 0 && values.length <= 20) {
|
||||
const options = values.map((option: any) => ({
|
||||
label: option.name || option.value,
|
||||
value: option.value,
|
||||
}));
|
||||
|
||||
props[field.fieldName] = Property.StaticDropdown({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: [
|
||||
{ label: '-- Keep Current Value --', value: '' },
|
||||
...options
|
||||
],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: values.length > 20
|
||||
? `Enter numeric value (${values.length} options available, leave empty to keep current)`
|
||||
: 'Enter value (leave empty to keep current)',
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'longtext': {
|
||||
props[field.fieldName] = Property.LongText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Leave empty to keep current value',
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'lookup': {
|
||||
let description = 'Record ID (leave empty to keep current)';
|
||||
if (field.fieldName.includes('account')) description = 'Account record ID (leave empty to keep current)';
|
||||
else if (field.fieldName.includes('contact')) description = 'Contact record ID (leave empty to keep current)';
|
||||
else if (field.fieldName.includes('owner')) description = 'User record ID for owner (leave empty to keep current)';
|
||||
else if (field.fieldName.includes('product')) description = 'Product record ID (leave empty to keep current)';
|
||||
else if (field.fieldName.includes('user')) description = 'User record ID (leave empty to keep current)';
|
||||
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Leave empty to keep current value',
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return props;
|
||||
} catch (error) {
|
||||
console.error('Error fetching update fields:', error);
|
||||
return {};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const updateRecordAction = createAction({
|
||||
name: 'update_record',
|
||||
displayName: 'Update Record',
|
||||
description: 'Update an existing record in Fireberry.',
|
||||
auth: fireberryAuth,
|
||||
props: {
|
||||
objectType: objectTypeDropdown,
|
||||
recordId: recordDropdown,
|
||||
fields: updateFields,
|
||||
},
|
||||
async run({ auth, propsValue }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType, recordId, fields } = propsValue;
|
||||
|
||||
if (!recordId) {
|
||||
throw new Error('Record ID is required');
|
||||
}
|
||||
|
||||
const fieldsObj = typeof fields === 'string' ? JSON.parse(fields) : fields;
|
||||
|
||||
if (typeof fieldsObj !== 'object' || fieldsObj === null) {
|
||||
throw new Error('Fields must be an object');
|
||||
}
|
||||
|
||||
const updateData: Record<string, any> = {};
|
||||
for (const [key, value] of Object.entries(fieldsObj)) {
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
updateData[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const recordToUpdate = { id: recordId, record: updateData };
|
||||
|
||||
return await client.batchUpdate(objectType as string, [recordToUpdate]);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
import { HttpMethod, httpClient, HttpRequest, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { AppConnectionValueForAuthProperty } from '@activepieces/pieces-framework';
|
||||
import { fireberryAuth } from '../..';
|
||||
|
||||
const FIREBERRY_API_BASE_URL = 'https://api.fireberry.com';
|
||||
const MAX_RETRIES = 3;
|
||||
const RETRY_DELAY_MS = 1000;
|
||||
|
||||
function delay(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function normalizeQueryParams(params?: Record<string, string | number | boolean>): Record<string, string> | undefined {
|
||||
if (!params) return undefined;
|
||||
const result: Record<string, string> = {};
|
||||
for (const key in params) {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
||||
result[key] = String(params[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export class FireberryClient {
|
||||
private apiKey: string;
|
||||
|
||||
constructor(apiKey: AppConnectionValueForAuthProperty<typeof fireberryAuth>) {
|
||||
this.apiKey = apiKey.secret_text;
|
||||
}
|
||||
|
||||
private parseError(error: any): string {
|
||||
if (error?.response?.body) {
|
||||
try {
|
||||
const body = typeof error.response.body === 'string' ? JSON.parse(error.response.body) : error.response.body;
|
||||
if (body?.error) {
|
||||
if (typeof body.error === 'string') return body.error;
|
||||
if (body.error.message) return body.error.message;
|
||||
}
|
||||
if (body?.message) return body.message;
|
||||
} catch {
|
||||
return 'Unknown error';
|
||||
}
|
||||
}
|
||||
if (error?.message) return error.message;
|
||||
return 'Unknown error';
|
||||
}
|
||||
|
||||
private shouldRetry(status: number): boolean {
|
||||
return status === 429 || (status >= 500 && status < 600);
|
||||
}
|
||||
|
||||
async request<T = unknown>({
|
||||
method,
|
||||
resourceUri,
|
||||
body,
|
||||
queryParams,
|
||||
}: {
|
||||
method: HttpMethod;
|
||||
resourceUri: string;
|
||||
body?: unknown;
|
||||
queryParams?: Record<string, string | number | boolean>;
|
||||
}): Promise<T> {
|
||||
const request: HttpRequest = {
|
||||
method,
|
||||
url: `${FIREBERRY_API_BASE_URL}${resourceUri}`,
|
||||
headers: {
|
||||
'tokenid': this.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body,
|
||||
queryParams: normalizeQueryParams(queryParams),
|
||||
timeout: 10000, // 10 seconds
|
||||
};
|
||||
let lastError: any = null;
|
||||
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
||||
try {
|
||||
const response = await httpClient.sendRequest<T>(request);
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response.body;
|
||||
} else {
|
||||
const errorMsg = this.parseError({ response });
|
||||
if (this.shouldRetry(response.status) && attempt < MAX_RETRIES - 1) {
|
||||
await delay(RETRY_DELAY_MS * (attempt + 1));
|
||||
continue;
|
||||
}
|
||||
throw new Error(`Fireberry API error (${response.status}): ${errorMsg}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
const status = error?.response?.status;
|
||||
if (status && this.shouldRetry(status) && attempt < MAX_RETRIES - 1) {
|
||||
await delay(RETRY_DELAY_MS * (attempt + 1));
|
||||
lastError = error;
|
||||
continue;
|
||||
}
|
||||
const errorMsg = this.parseError(error);
|
||||
throw new Error(`Fireberry API error${status ? ` (${status})` : ''}: ${errorMsg}`);
|
||||
}
|
||||
}
|
||||
throw new Error(`Fireberry API error: ${this.parseError(lastError)}`);
|
||||
}
|
||||
|
||||
async getObjectsMetadata(): Promise<{ success: boolean; data: Array<{ name: string; systemName: string; objectType: string }> }> {
|
||||
return this.request<{ success: boolean; data: Array<{ name: string; systemName: string; objectType: string }> }>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: '/metadata/records',
|
||||
});
|
||||
}
|
||||
|
||||
async getObjectFieldsMetadata(object: string): Promise<{ success: boolean; data: Array<{ label: string; fieldName: string; systemFieldTypeId: string; systemName: string }> }> {
|
||||
return this.request<{ success: boolean; data: Array<{ label: string; fieldName: string; systemFieldTypeId: string; systemName: string }> }>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/metadata/records/${object}/fields`,
|
||||
});
|
||||
}
|
||||
|
||||
async getPicklistValues(object: string, fieldName: string): Promise<{ success: boolean; data: { values: Array<{ name: string; value: string }> } }> {
|
||||
return this.request<{ success: boolean; data: { values: Array<{ name: string; value: string }> } }>({
|
||||
method: HttpMethod.GET,
|
||||
resourceUri: `/metadata/records/${object}/fields/${fieldName}/values`,
|
||||
});
|
||||
}
|
||||
|
||||
async batchCreate(object: string, records: any[]): Promise<any> {
|
||||
return this.request({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/api/v3/record/${object}/batch/create`,
|
||||
body: { data: records },
|
||||
});
|
||||
}
|
||||
|
||||
async batchUpdate(object: string, records: any[]): Promise<any> {
|
||||
return this.request({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/api/v3/record/${object}/batch/update`,
|
||||
body: { data: records },
|
||||
});
|
||||
}
|
||||
|
||||
async batchDelete(object: string, ids: string[]): Promise<any> {
|
||||
return this.request({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: `/api/v3/record/${object}/batch/delete`,
|
||||
body: { data: ids },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
import { Property } from '@activepieces/pieces-framework';
|
||||
import { FireberryClient } from './client';
|
||||
import { fireberryAuth } from '../..';
|
||||
|
||||
export const objectTypeDropdown = Property.Dropdown({
|
||||
displayName: 'Object Type',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
auth: fireberryAuth,
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Connect your Fireberry account',
|
||||
};
|
||||
}
|
||||
const client = new FireberryClient(auth);
|
||||
const metadata = await client.getObjectsMetadata();
|
||||
const options = metadata.data.map(obj => ({
|
||||
label: obj.name,
|
||||
value: obj.systemName,
|
||||
}));
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const objectFields = Property.DynamicProperties({
|
||||
displayName: 'Fields',
|
||||
refreshers: ['objectType'],
|
||||
required: true,
|
||||
auth: fireberryAuth,
|
||||
props: async ({ auth, objectType }) => {
|
||||
if (!auth || !objectType) return {};
|
||||
const objectTypeStr = typeof objectType === 'string' ? objectType : (objectType as { value: string })?.value;
|
||||
const client = new FireberryClient(auth);
|
||||
const metadata = await client.getObjectFieldsMetadata(objectTypeStr);
|
||||
const props: Record<string, any> = {};
|
||||
|
||||
const fieldTypeMap: Record<string, string> = {
|
||||
'a1e7ed6f-5083-477b-b44c-9943a6181359': 'text',
|
||||
'ce972d02-5013-46d4-9d1d-f09df1ac346a': 'datetime',
|
||||
'6a34bfe3-fece-4da1-9136-a7b1e5ae3319': 'number',
|
||||
'a8fcdf65-91bc-46fd-82f6-1234758345a1': 'lookup',
|
||||
'b4919f2e-2996-48e4-a03c-ba39fb64386c': 'picklist',
|
||||
'80108f9d-1e75-40fa-9fa9-02be4ddc1da1': 'longtext',
|
||||
};
|
||||
|
||||
const picklistCache: Record<string, any> = {};
|
||||
const picklistFields = metadata.data.filter(field =>
|
||||
fieldTypeMap[field.systemFieldTypeId] === 'picklist'
|
||||
);
|
||||
|
||||
for (const field of picklistFields) {
|
||||
const largeLists = ['objecttypecode', 'resultcode'];
|
||||
if (!largeLists.includes(field.fieldName.toLowerCase())) {
|
||||
try {
|
||||
const picklistData = await client.getPicklistValues(objectTypeStr, field.fieldName);
|
||||
if (picklistData.data?.values && Array.isArray(picklistData.data.values)) {
|
||||
picklistCache[field.fieldName] = picklistData.data.values;
|
||||
}
|
||||
} catch (error) {
|
||||
picklistCache[field.fieldName] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const field of metadata.data) {
|
||||
const systemFields = ['createdby', 'modifiedby', 'deletedby', 'createdon', 'modifiedon', 'deletedon'];
|
||||
if (field.fieldName.endsWith('id') && !field.label) {
|
||||
continue;
|
||||
}
|
||||
if (systemFields.includes(field.fieldName.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fieldType = fieldTypeMap[field.systemFieldTypeId] || 'text';
|
||||
const isRequired = false;
|
||||
|
||||
switch (fieldType) {
|
||||
case 'text':
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
});
|
||||
break;
|
||||
case 'number':
|
||||
props[field.fieldName] = Property.Number({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
});
|
||||
break;
|
||||
case 'datetime':
|
||||
props[field.fieldName] = Property.DateTime({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Date and time in UTC format',
|
||||
});
|
||||
break;
|
||||
case 'picklist':{
|
||||
const largeLists = ['objecttypecode', 'resultcode'];
|
||||
if (largeLists.includes(field.fieldName.toLowerCase())) {
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Enter the numeric value for this field',
|
||||
});
|
||||
} else {
|
||||
const values = picklistCache[field.fieldName] || [];
|
||||
if (values.length > 0 && values.length <= 20) {
|
||||
const options = values.map((option: any) => ({
|
||||
label: option.name || option.value,
|
||||
value: option.value,
|
||||
}));
|
||||
|
||||
props[field.fieldName] = Property.StaticDropdown({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
options: {
|
||||
disabled: false,
|
||||
options,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: values.length > 20
|
||||
? `Enter numeric value (${values.length} options available)`
|
||||
: 'Enter the value for this field',
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'longtext':{
|
||||
props[field.fieldName] = Property.LongText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: 'Long text content',
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'lookup':{
|
||||
let description = 'Record ID (GUID)';
|
||||
if (field.fieldName.includes('account')) description = 'Account record ID';
|
||||
else if (field.fieldName.includes('contact')) description = 'Contact record ID';
|
||||
else if (field.fieldName.includes('owner')) description = 'User record ID for owner';
|
||||
else if (field.fieldName.includes('product')) description = 'Product record ID';
|
||||
else if (field.fieldName.includes('user')) description = 'User record ID';
|
||||
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
props[field.fieldName] = Property.ShortText({
|
||||
displayName: field.label || field.fieldName,
|
||||
required: isRequired,
|
||||
description: `${fieldType} field`,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return props;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,216 @@
|
||||
import { createTrigger, TriggerStrategy, Property } from '@activepieces/pieces-framework';
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { fireberryAuth } from '../../index';
|
||||
import { objectTypeDropdown } from '../common/props';
|
||||
import { FireberryClient } from '../common/client';
|
||||
|
||||
export const recordCreatedOrUpdatedTrigger = createTrigger({
|
||||
name: 'record_created_or_updated',
|
||||
displayName: 'Record Created or Updated',
|
||||
description: 'Fires when a record is created or updated in Fireberry.',
|
||||
auth: fireberryAuth,
|
||||
props: {
|
||||
objectType: objectTypeDropdown,
|
||||
triggerType: Property.StaticDropdown({
|
||||
displayName: 'Trigger Type',
|
||||
required: true,
|
||||
defaultValue: 'both',
|
||||
options: {
|
||||
disabled: false,
|
||||
options: [
|
||||
{ label: 'Created or Updated', value: 'both' },
|
||||
{ label: 'Created Only', value: 'created' },
|
||||
{ label: 'Updated Only', value: 'updated' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
lookbackMinutes: Property.Number({
|
||||
displayName: 'Lookback Period (minutes)',
|
||||
required: false,
|
||||
defaultValue: 60,
|
||||
description: 'How far back to look for records on first run (default: 60 minutes)',
|
||||
}),
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
sampleData: {
|
||||
accountname: "Sample Account",
|
||||
emailaddress1: "sample@example.com",
|
||||
createdon: "2025-07-17T10:39:30.003",
|
||||
modifiedon: "2025-07-17T10:39:30.003",
|
||||
accountid: "12345678-1234-1234-1234-123456789abc",
|
||||
},
|
||||
async test({ auth, propsValue }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType } = propsValue;
|
||||
|
||||
if (!objectType) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const objectsMetadata = await client.getObjectsMetadata();
|
||||
const targetObject = objectsMetadata.data.find(obj => obj.systemName === objectType);
|
||||
|
||||
if (!targetObject) {
|
||||
throw new Error(`Object type '${objectType}' not found`);
|
||||
}
|
||||
|
||||
const objectNumber = parseInt(targetObject.objectType);
|
||||
|
||||
const sevenDaysAgo = new Date(Date.now() - (7 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0];
|
||||
|
||||
const response = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
ObjectName: string;
|
||||
SystemName: string;
|
||||
ObjectType: number;
|
||||
PrimaryKey: string;
|
||||
PrimaryField: string;
|
||||
PageNum: number;
|
||||
SortBy: string;
|
||||
SortBy_Desc: boolean;
|
||||
IsLastPage: boolean;
|
||||
Columns: Array<Record<string, any>>;
|
||||
Data: Array<Record<string, any>>;
|
||||
};
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: '/api/query',
|
||||
body: {
|
||||
objecttype: objectNumber,
|
||||
query: `modifiedon >= '${sevenDaysAgo}'`,
|
||||
sort_by: 'modifiedon',
|
||||
sort_type: 'desc',
|
||||
page_size: 3,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error('Failed to fetch sample data from Fireberry');
|
||||
}
|
||||
|
||||
const records = response.data.Data || [];
|
||||
|
||||
if (records.length === 0) {
|
||||
const fallbackResponse = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
Data: Array<Record<string, any>>;
|
||||
};
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: '/api/query',
|
||||
body: {
|
||||
objecttype: objectNumber,
|
||||
sort_by: 'modifiedon',
|
||||
sort_type: 'desc',
|
||||
page_size: 3,
|
||||
},
|
||||
});
|
||||
|
||||
if (fallbackResponse.success && fallbackResponse.data.Data) {
|
||||
return fallbackResponse.data.Data;
|
||||
}
|
||||
}
|
||||
|
||||
return records;
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('Failed to generate sample data:', error);
|
||||
return [{
|
||||
[objectType === 'Contact' ? 'firstname' : 'accountname']: 'Sample Record',
|
||||
createdon: new Date().toISOString(),
|
||||
modifiedon: new Date().toISOString(),
|
||||
}];
|
||||
}
|
||||
},
|
||||
async onEnable({ store }) {
|
||||
await store.put('lastPollTime', new Date().toISOString());
|
||||
},
|
||||
async onDisable({ store }) {
|
||||
await store.delete('lastPollTime');
|
||||
},
|
||||
async run({ auth, propsValue, store }) {
|
||||
const client = new FireberryClient(auth);
|
||||
const { objectType, triggerType, lookbackMinutes } = propsValue;
|
||||
|
||||
let lastPollTime = await store.get<string>('lastPollTime');
|
||||
|
||||
if (!lastPollTime) {
|
||||
const lookback = lookbackMinutes || 60;
|
||||
const cutoffTime = new Date(Date.now() - (lookback * 60 * 1000));
|
||||
lastPollTime = cutoffTime.toISOString();
|
||||
}
|
||||
|
||||
const objectsMetadata = await client.getObjectsMetadata();
|
||||
const targetObject = objectsMetadata.data.find(obj => obj.systemName === objectType);
|
||||
|
||||
if (!targetObject) {
|
||||
throw new Error(`Object type '${objectType}' not found`);
|
||||
}
|
||||
|
||||
const objectNumber = parseInt(targetObject.objectType);
|
||||
|
||||
let query = '';
|
||||
const cutoffDate = new Date(lastPollTime).toISOString().split('T')[0];
|
||||
|
||||
if (triggerType === 'created') {
|
||||
query = `createdon >= '${cutoffDate}'`;
|
||||
} else if (triggerType === 'updated') {
|
||||
query = `modifiedon >= '${cutoffDate}'`;
|
||||
} else {
|
||||
query = `modifiedon >= '${cutoffDate}'`;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.request<{
|
||||
success: boolean;
|
||||
data: {
|
||||
ObjectName: string;
|
||||
SystemName: string;
|
||||
ObjectType: number;
|
||||
PrimaryKey: string;
|
||||
PrimaryField: string;
|
||||
PageNum: number;
|
||||
SortBy: string;
|
||||
SortBy_Desc: boolean;
|
||||
IsLastPage: boolean;
|
||||
Columns: Array<Record<string, any>>;
|
||||
Data: Array<Record<string, any>>;
|
||||
};
|
||||
}>({
|
||||
method: HttpMethod.POST,
|
||||
resourceUri: '/api/query',
|
||||
body: {
|
||||
objecttype: objectNumber,
|
||||
query: query,
|
||||
sort_by: 'modifiedon',
|
||||
sort_type: 'desc',
|
||||
page_size: 50,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error('Failed to fetch records from Fireberry');
|
||||
}
|
||||
|
||||
const records = response.data.Data || [];
|
||||
|
||||
await store.put('lastPollTime', new Date().toISOString());
|
||||
|
||||
return records.reverse();
|
||||
|
||||
} catch (error: any) {
|
||||
if (error.message?.includes('429')) {
|
||||
throw new Error('Rate limit exceeded. Please try again later.');
|
||||
}
|
||||
if (error.message?.includes('401') || error.message?.includes('403')) {
|
||||
throw new Error('Authentication failed. Please check your Fireberry API key.');
|
||||
}
|
||||
|
||||
console.error('Fireberry trigger error:', error);
|
||||
throw new Error(`Failed to fetch records: ${error.message || 'Unknown error'}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"importHelpers": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noPropertyAccessFromIndexSignature": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user