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:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,33 @@
{
"extends": [
"../../../../.eslintrc.base.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {}
},
{
"files": [
"*.ts",
"*.tsx"
],
"rules": {}
},
{
"files": [
"*.js",
"*.jsx"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-softr
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build pieces-softr` to build the library.

View File

@@ -0,0 +1,10 @@
{
"name": "@activepieces/piece-softr",
"version": "0.0.8",
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0"
}
}

View File

@@ -0,0 +1,65 @@
{
"name": "pieces-softr",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/softr/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/softr",
"tsConfig": "packages/pieces/community/softr/tsconfig.lib.json",
"packageJson": "packages/pieces/community/softr/package.json",
"main": "packages/pieces/community/softr/src/index.ts",
"assets": [
"packages/pieces/community/softr/*.md",
{
"input": "packages/pieces/community/softr/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/softr",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "Du kannst deinen API-Schlüssel unter [API-Einstellungen](https://studio.softr.io/user/apisettings).",
"Create App User": "App-Benutzer erstellen",
"Create Database Record": "Datenbank-Datensatz erstellen",
"Delete App User": "App-Benutzer löschen",
"Delete Database Record": "Datenbank-Eintrag löschen",
"Find Database Record": "Datenbank-Eintrag finden",
"Update Database Record": "Datenbank-Eintrag aktualisieren",
"Custom API Call": "Eigener API-Aufruf",
"Creates a new user inside a Softr app.": "Erstellt einen neuen Benutzer innerhalb einer Softr-App.",
"Creates a new record.": "Erstellt einen neuen Datensatz.",
"Deletes a user from a Softr app.": "Löscht einen Benutzer aus einer Softr-App.",
"Deletes a existing database record.": "Löscht einen vorhandenen Datenbankeintrag.",
"Finds a record in table.": "Findet einen Datensatz in der Tabelle.",
"Updates an existing database record.": "Aktualisiert einen vorhandenen Datensatz.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Email": "E-Mail",
"Name": "Name",
"Password": "Kennwort",
"Domain": "Domäne",
"Generate Magic Link": "Magic Link generieren",
"Database ID": "Datenbank-ID",
"Table ID": "Table ID",
"Fields": "Felder",
"User Email": "Benutzer-E-Mail",
"Softr Domain": "Softr-Domain",
"Record ID": "Datensatz-ID",
"Field": "Feld",
"Field Value": "Feldwert",
"Method": "Methode",
"Headers": "Kopfzeilen",
"Query Parameters": "Abfrageparameter",
"Body": "Körper",
"Response is Binary ?": "Antwort ist binär?",
"No Error on Failure": "Kein Fehler bei Fehler",
"Timeout (in seconds)": "Timeout (in Sekunden)",
"The email address of the new user.": "Die E-Mail-Adresse des neuen Benutzers.",
"The full name of the new user.": "Der vollständige Name des neuen Benutzers.",
"The password for the new user.": "Das Passwort für den neuen Benutzer.",
"The domain or subdomain of the Softr app where the user will be created.": "Die Domain oder Subdomain der Softr-App, in der der Benutzer erstellt wird.",
"If checked, a magic link will be generated for the user.": "Wenn aktiviert, wird ein magischer Link für den Benutzer generiert.",
"Select the database to insert the record into": "Wählen Sie die Datenbank zum Einfügen des Datensatzes aus",
"Select the table to insert the record into": "Wählen Sie die Tabelle zum Einfügen des Datensatzes aus",
"The email address of the user to delete.": "Die E-Mail-Adresse des zu löschenden Benutzers.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "Domain oder Subdomain der Softr-App (z.B. yourdomain.com oder subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New Database Record": "Neuer Datenbank-Datensatz",
"Triggers when a new record is added.": "Wird ausgelöst, wenn ein neuer Datensatz hinzugefügt wird."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "Puedes obtener tu clave API de [Configuración de API](https://studio.softr.io/user/apisettings).",
"Create App User": "Crear Usuario App",
"Create Database Record": "Crear registro de base de datos",
"Delete App User": "Eliminar Usuario App",
"Delete Database Record": "Eliminar registro de base de datos",
"Find Database Record": "Buscar registro de base de datos",
"Update Database Record": "Actualizar registro de base de datos",
"Custom API Call": "Llamada API personalizada",
"Creates a new user inside a Softr app.": "Crea un nuevo usuario dentro de una aplicación Softr.",
"Creates a new record.": "Crea un nuevo registro.",
"Deletes a user from a Softr app.": "Elimina un usuario de una aplicación Softr.",
"Deletes a existing database record.": "Elimina un registro de base de datos existente.",
"Finds a record in table.": "Encuentra un registro en la tabla.",
"Updates an existing database record.": "Actualiza un registro de base de datos existente.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Email": "E-mail",
"Name": "Nombre",
"Password": "Contraseña",
"Domain": "Dominio",
"Generate Magic Link": "Generar enlace mágico",
"Database ID": "ID de base de datos",
"Table ID": "Table ID",
"Fields": "Campos",
"User Email": "Email de usuario",
"Softr Domain": "Dominio Softr",
"Record ID": "ID de registro",
"Field": "Campo",
"Field Value": "Valor del campo",
"Method": "Método",
"Headers": "Encabezados",
"Query Parameters": "Parámetros de consulta",
"Body": "Cuerpo",
"Response is Binary ?": "¿Respuesta es binaria?",
"No Error on Failure": "No hay ningún error en fallo",
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
"The email address of the new user.": "La dirección de correo electrónico del nuevo usuario.",
"The full name of the new user.": "El nombre completo del nuevo usuario.",
"The password for the new user.": "La contraseña para el nuevo usuario.",
"The domain or subdomain of the Softr app where the user will be created.": "El dominio o subdominio de la aplicación Softr donde se creará el usuario.",
"If checked, a magic link will be generated for the user.": "Si está marcado, se generará un enlace mágico para el usuario.",
"Select the database to insert the record into": "Seleccione la base de datos en la que insertar el registro",
"Select the table to insert the record into": "Seleccione la tabla en la que insertar el registro",
"The email address of the user to delete.": "La dirección de correo electrónico del usuario a eliminar.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "El dominio o subdominio de la aplicación Softr (por ejemplo, yourdomain.com o subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New Database Record": "Nuevo registro de base de datos",
"Triggers when a new record is added.": "Se activa cuando se añade un nuevo registro."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "Vous pouvez obtenir votre clé API dans [API Settings](https://studio.softr.io/user/apisettings).",
"Create App User": "Créer un utilisateur de l'application",
"Create Database Record": "Créer un enregistrement de base de données",
"Delete App User": "Supprimer l'utilisateur de l'application",
"Delete Database Record": "Supprimer l'enregistrement de la base de données",
"Find Database Record": "Trouver l'enregistrement de la base de données",
"Update Database Record": "Mettre à jour l'enregistrement de la base de données",
"Custom API Call": "Appel d'API personnalisé",
"Creates a new user inside a Softr app.": "Crée un nouvel utilisateur dans une application Softr.",
"Creates a new record.": "Crée un nouvel enregistrement.",
"Deletes a user from a Softr app.": "Supprime un utilisateur d'une application Softr.",
"Deletes a existing database record.": "Supprime un enregistrement de base de données existant.",
"Finds a record in table.": "Trouve un enregistrement dans le tableau.",
"Updates an existing database record.": "Met à jour un enregistrement de base de données existant.",
"Make a custom API call to a specific endpoint": "Passer un appel API personnalisé à un endpoint spécifique",
"Email": "Courriel",
"Name": "Nom",
"Password": "Password",
"Domain": "Domaine",
"Generate Magic Link": "Générer un lien magique",
"Database ID": "ID de la base de données",
"Table ID": "Table ID",
"Fields": "Champs",
"User Email": "E-mail de l'utilisateur",
"Softr Domain": "Domaine Softr",
"Record ID": "ID de l'enregistrement",
"Field": "Champ",
"Field Value": "Valeur du champ",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'expiration (en secondes)",
"The email address of the new user.": "L'adresse email du nouvel utilisateur.",
"The full name of the new user.": "Le nom complet du nouvel utilisateur.",
"The password for the new user.": "Le mot de passe pour le nouvel utilisateur.",
"The domain or subdomain of the Softr app where the user will be created.": "Le domaine ou sous-domaine de l'application Softr où l'utilisateur sera créé.",
"If checked, a magic link will be generated for the user.": "Si coché, un lien magique sera généré pour l'utilisateur.",
"Select the database to insert the record into": "Sélectionnez la base de données dans laquelle insérer l'enregistrement",
"Select the table to insert the record into": "Sélectionnez la table dans laquelle insérer l'enregistrement",
"The email address of the user to delete.": "L'adresse e-mail de l'utilisateur à supprimer.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "Le domaine ou sous-domaine de l'application Softr (par exemple, yourdomain.com ou sous-domain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Database Record": "Nouvel enregistrement de base de données",
"Triggers when a new record is added.": "Déclenche lorsqu'un nouvel enregistrement est ajouté."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "API キーは [API 設定](https://studio.softr.io/user/apisettings) から取得できます。",
"Create App User": "アプリユーザーを作成",
"Create Database Record": "データベースレコードを作成",
"Delete App User": "アプリユーザーを削除",
"Delete Database Record": "データベースレコードを削除",
"Find Database Record": "データベースレコードを検索",
"Update Database Record": "データベースレコードを更新",
"Custom API Call": "カスタムAPI通話",
"Creates a new user inside a Softr app.": "Softr アプリ内で新規ユーザーを作成します。",
"Creates a new record.": "新規レコードを作成",
"Deletes a user from a Softr app.": "Softr アプリからユーザーを削除します。",
"Deletes a existing database record.": "既存のデータベースレコードを削除します。",
"Finds a record in table.": "テーブル内のレコードを検索します。",
"Updates an existing database record.": "既存のデータベースレコードを更新します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Email": "Eメールアドレス",
"Name": "名前",
"Password": "パスワード",
"Domain": "ドメイン",
"Generate Magic Link": "マジックリンクを生成する",
"Database ID": "データベースID",
"Table ID": "Table ID",
"Fields": "フィールド",
"User Email": "ユーザーのメールアドレス",
"Softr Domain": "Softr ドメイン",
"Record ID": "レコードID",
"Field": "フィールド",
"Field Value": "フィールド値",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"The email address of the new user.": "新しいユーザーのメールアドレス",
"The full name of the new user.": "新しいユーザーのフルネーム。",
"The password for the new user.": "新しいユーザーのパスワード",
"The domain or subdomain of the Softr app where the user will be created.": "ユーザーが作成されるSoftrアプリのドメインまたはサブドメイン。",
"If checked, a magic link will be generated for the user.": "チェックされている場合、ユーザーにマジックリンクが生成されます。",
"Select the database to insert the record into": "レコードを挿入するデータベースを選択します",
"Select the table to insert the record into": "レコードを挿入するテーブルを選択します",
"The email address of the user to delete.": "削除するユーザーのメールアドレス",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "Softr アプリのドメインまたはサブドメイン (例: yourdomain.com または subdomain.softtr.app)。",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New Database Record": "新しいデータベースレコード",
"Triggers when a new record is added.": "新しいレコードが追加されたときにトリガーします。"
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "U kunt uw API-sleutel verkrijgen via [API Settings](https://studio.softr.io/user/apisettings).",
"Create App User": "Maak app-gebruiker aan",
"Create Database Record": "Database Record Maken",
"Delete App User": "Verwijder App Gebruiker",
"Delete Database Record": "Databaserecord verwijderen",
"Find Database Record": "Vind Database Record",
"Update Database Record": "Databaserecord bijwerken",
"Custom API Call": "Custom API Call",
"Creates a new user inside a Softr app.": "Maakt een nieuwe gebruiker in een Softr app.",
"Creates a new record.": "Maakt een nieuw record aan.",
"Deletes a user from a Softr app.": "Verwijdert een gebruiker van een Softr app.",
"Deletes a existing database record.": "Verwijdert een bestaande databaserecord.",
"Finds a record in table.": "Vindt een record in de tabel.",
"Updates an existing database record.": "Werkt een bestaand databaserecord bij.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Email": "E-mail",
"Name": "Naam",
"Password": "Wachtwoord",
"Domain": "Domein",
"Generate Magic Link": "Genereer Magic Link",
"Database ID": "Database ID",
"Table ID": "Table ID",
"Fields": "Velden",
"User Email": "E-mail van gebruiker",
"Softr Domain": "Softr domein",
"Record ID": "Record ID",
"Field": "Veld",
"Field Value": "Veld waarde",
"Method": "Methode",
"Headers": "Kopteksten",
"Query Parameters": "Query parameters",
"Body": "Lichaam",
"Response is Binary ?": "Antwoord is binair?",
"No Error on Failure": "Geen fout bij fout",
"Timeout (in seconds)": "Time-out (in seconden)",
"The email address of the new user.": "Het e-mailadres van de nieuwe gebruiker.",
"The full name of the new user.": "De volledige naam van de nieuwe gebruiker.",
"The password for the new user.": "Het wachtwoord voor de nieuwe gebruiker.",
"The domain or subdomain of the Softr app where the user will be created.": "Het domein of subdomein van de Softr app waar de gebruiker wordt gemaakt.",
"If checked, a magic link will be generated for the user.": "Indien aangevinkt, wordt een magische link gegenereerd voor de gebruiker.",
"Select the database to insert the record into": "Selecteer de database om de record in te voegen",
"Select the table to insert the record into": "Selecteer de tabel om de record in te voegen",
"The email address of the user to delete.": "Het e-mailadres van de te verwijderen gebruiker",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "Het domein of subdomein van de Softr app (bijv. jouwdomein.com of subdomein.softr.app).",
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New Database Record": "Nieuwe Database Record",
"Triggers when a new record is added.": "Triggert wanneer een nieuw record wordt toegevoegd."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "Você pode obter sua chave de API em [Configurações da API](https://studio.softr.io/user/apisettings).",
"Create App User": "Criar Usuário do Aplicativo",
"Create Database Record": "Criar banco de dados",
"Delete App User": "Excluir Usuário do Aplicativo",
"Delete Database Record": "Apagar Banco de Dados",
"Find Database Record": "Localizar Banco de Dados",
"Update Database Record": "Atualizar registro do banco",
"Custom API Call": "Chamada de API personalizada",
"Creates a new user inside a Softr app.": "Cria um novo usuário dentro de um aplicativo Softr.",
"Creates a new record.": "Cria um novo registro.",
"Deletes a user from a Softr app.": "Exclui um usuário de um aplicativo Softr.",
"Deletes a existing database record.": "Exclui um registro de banco de dados existente.",
"Finds a record in table.": "Encontrar um registro na tabela.",
"Updates an existing database record.": "Atualiza um registro do banco de dados existente.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Email": "e-mail",
"Name": "Nome",
"Password": "Senha",
"Domain": "Domínio",
"Generate Magic Link": "Gerar Link Mágico",
"Database ID": "ID do banco",
"Table ID": "Table ID",
"Fields": "campos",
"User Email": "Email do Usuário",
"Softr Domain": "Domínio Suave",
"Record ID": "ID do Registro",
"Field": "Campo",
"Field Value": "Valor do Campo",
"Method": "Método",
"Headers": "Cabeçalhos",
"Query Parameters": "Parâmetros da consulta",
"Body": "Conteúdo",
"Response is Binary ?": "A resposta é binária ?",
"No Error on Failure": "Nenhum erro no Failure",
"Timeout (in seconds)": "Tempo limite (em segundos)",
"The email address of the new user.": "O endereço de e-mail do novo usuário.",
"The full name of the new user.": "Nome completo do novo usuário.",
"The password for the new user.": "A senha para o novo usuário.",
"The domain or subdomain of the Softr app where the user will be created.": "O domínio ou subdomínio do aplicativo Softr onde o usuário será criado.",
"If checked, a magic link will be generated for the user.": "Se marcado, um link mágico será gerado para o usuário.",
"Select the database to insert the record into": "Selecione o banco de dados para inserir o registro",
"Select the table to insert the record into": "Selecione a tabela para inserir o registro",
"The email address of the user to delete.": "O endereço de e-mail do usuário a ser removido.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "O domínio ou subdomínio do aplicativo Softr (ex.: seudominio.com ou subdomínio.softr.app).",
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New Database Record": "Novo banco de dados",
"Triggers when a new record is added.": "Dispara quando um novo registro for adicionado."
}

View File

@@ -0,0 +1,55 @@
{
"Softr": "Софтр",
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "Вы можете получить ваш ключ API в [Настройки API](https://studio.softr.io/user/apisettings).",
"Create App User": "Создать пользователя приложения",
"Create Database Record": "Создать запись базы данных",
"Delete App User": "Удалить пользователя приложения",
"Delete Database Record": "Удалить запись базы данных",
"Find Database Record": "Найти запись базы данных",
"Update Database Record": "Обновить запись базы данных",
"Custom API Call": "Пользовательский вызов API",
"Creates a new user inside a Softr app.": "Создает нового пользователя в Softr приложении.",
"Creates a new record.": "Создает новую запись.",
"Deletes a user from a Softr app.": "Удаляет пользователя из Softr приложения.",
"Deletes a existing database record.": "Удаляет существующую запись базы данных.",
"Finds a record in table.": "Находит запись в таблице.",
"Updates an existing database record.": "Обновляет существующую базу данных.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Email": "Почта",
"Name": "Наименование",
"Password": "Пароль",
"Domain": "Домен",
"Generate Magic Link": "Создать волшебную ссылку",
"Database ID": "ID базы данных",
"Table ID": "Table ID",
"Fields": "Поля",
"User Email": "Email пользователя",
"Softr Domain": "Домен Softr",
"Record ID": "ID записи",
"Field": "Поле",
"Field Value": "Значение поля",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"The email address of the new user.": "Адрес электронной почты нового пользователя.",
"The full name of the new user.": "Полное имя нового пользователя.",
"The password for the new user.": "Пароль для нового пользователя.",
"The domain or subdomain of the Softr app where the user will be created.": "Домен или поддомен приложения Softr, в котором будет создан пользователь.",
"If checked, a magic link will be generated for the user.": "При отмеченной опции для пользователя будет создана волшебная ссылка.",
"Select the database to insert the record into": "Выберите базу данных для вставки записи в",
"Select the table to insert the record into": "Выберите таблицу для вставки записи в",
"The email address of the user to delete.": "Адрес электронной почты пользователя для удаления.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "Домен или поддон приложения Softr (например, yourdomain.com или subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"New Database Record": "Новая запись базы данных",
"Triggers when a new record is added.": "Триггеры при добавлении новой записи."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).",
"Create App User": "Create App User",
"Create Database Record": "Create Database Record",
"Delete App User": "Delete App User",
"Delete Database Record": "Delete Database Record",
"Find Database Record": "Find Database Record",
"Update Database Record": "Update Database Record",
"Custom API Call": "Custom API Call",
"Creates a new user inside a Softr app.": "Creates a new user inside a Softr app.",
"Creates a new record.": "Creates a new record.",
"Deletes a user from a Softr app.": "Deletes a user from a Softr app.",
"Deletes a existing database record.": "Deletes a existing database record.",
"Finds a record in table.": "Finds a record in table.",
"Updates an existing database record.": "Updates an existing database record.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Email": "Email",
"Name": "Name",
"Password": "Password",
"Domain": "Domain",
"Generate Magic Link": "Generate Magic Link",
"Database ID": "Database ID",
"Table ID": "Table ID",
"Fields": "Fields",
"User Email": "User Email",
"Softr Domain": "Softr Domain",
"Record ID": "Record ID",
"Field": "Field",
"Field Value": "Field Value",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"The email address of the new user.": "The email address of the new user.",
"The full name of the new user.": "The full name of the new user.",
"The password for the new user.": "The password for the new user.",
"The domain or subdomain of the Softr app where the user will be created.": "The domain or subdomain of the Softr app where the user will be created.",
"If checked, a magic link will be generated for the user.": "If checked, a magic link will be generated for the user.",
"Select the database to insert the record into": "Select the database to insert the record into",
"Select the table to insert the record into": "Select the table to insert the record into",
"The email address of the user to delete.": "The email address of the user to delete.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Database Record": "New Database Record",
"Triggers when a new record is added.": "Triggers when a new record is added."
}

View File

@@ -0,0 +1,55 @@
{
"Softr": "Softr",
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).",
"Create App User": "Create App User",
"Create Database Record": "Create Database Record",
"Delete App User": "Delete App User",
"Delete Database Record": "Delete Database Record",
"Find Database Record": "Find Database Record",
"Update Database Record": "Update Database Record",
"Custom API Call": "Custom API Call",
"Creates a new user inside a Softr app.": "Creates a new user inside a Softr app.",
"Creates a new record.": "Creates a new record.",
"Deletes a user from a Softr app.": "Deletes a user from a Softr app.",
"Deletes a existing database record.": "Deletes a existing database record.",
"Finds a record in table.": "Finds a record in table.",
"Updates an existing database record.": "Updates an existing database record.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Email": "Email",
"Name": "Name",
"Password": "Password",
"Domain": "Domain",
"Generate Magic Link": "Generate Magic Link",
"Database ID": "Database ID",
"Table ID": "Table ID",
"Fields": "Fields",
"User Email": "User Email",
"Softr Domain": "Softr Domain",
"Record ID": "Record ID",
"Field": "Field",
"Field Value": "Field Value",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"The email address of the new user.": "The email address of the new user.",
"The full name of the new user.": "The full name of the new user.",
"The password for the new user.": "The password for the new user.",
"The domain or subdomain of the Softr app where the user will be created.": "The domain or subdomain of the Softr app where the user will be created.",
"If checked, a magic link will be generated for the user.": "If checked, a magic link will be generated for the user.",
"Select the database to insert the record into": "Select the database to insert the record into",
"Select the table to insert the record into": "Select the table to insert the record into",
"The email address of the user to delete.": "The email address of the user to delete.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New Database Record": "New Database Record",
"Triggers when a new record is added.": "Triggers when a new record is added."
}

View File

@@ -0,0 +1,56 @@
{
"You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).": "You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).",
"Create App User": "Create App User",
"Create Database Record": "Create Database Record",
"Delete App User": "Delete App User",
"Delete Database Record": "Delete Database Record",
"Find Database Record": "Find Database Record",
"Update Database Record": "Update Database Record",
"Custom API Call": "自定义 API 呼叫",
"Creates a new user inside a Softr app.": "Creates a new user inside a Softr app.",
"Creates a new record.": "Creates a new record.",
"Deletes a user from a Softr app.": "Deletes a user from a Softr app.",
"Deletes a existing database record.": "Deletes a existing database record.",
"Finds a record in table.": "Finds a record in table.",
"Updates an existing database record.": "Updates an existing database record.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Email": "电子邮件地址",
"Name": "名称",
"Password": "密码",
"Domain": "Domain",
"Generate Magic Link": "Generate Magic Link",
"Database ID": "Database ID",
"Table ID": "Table ID",
"Fields": "Fields",
"User Email": "User Email",
"Softr Domain": "Softr Domain",
"Record ID": "Record ID",
"Field": "字段",
"Field Value": "Field Value",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"The email address of the new user.": "The email address of the new user.",
"The full name of the new user.": "The full name of the new user.",
"The password for the new user.": "The password for the new user.",
"The domain or subdomain of the Softr app where the user will be created.": "The domain or subdomain of the Softr app where the user will be created.",
"If checked, a magic link will be generated for the user.": "If checked, a magic link will be generated for the user.",
"Select the database to insert the record into": "Select the database to insert the record into",
"Select the table to insert the record into": "Select the table to insert the record into",
"The email address of the user to delete.": "The email address of the user to delete.",
"The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).": "The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New Database Record": "New Database Record",
"Triggers when a new record is added.": "Triggers when a new record is added."
}

View File

@@ -0,0 +1,39 @@
import { createPiece } from '@activepieces/pieces-framework';
import { SoftrAuth } from './lib/common/auth';
import { createDatabaseRecord } from './lib/actions/create-database-record';
import { createAppUser } from './lib/actions/create-app-user';
import { deleteAppUser } from './lib/actions/delete-app-user';
import { deleteDatabaseRecord } from './lib/actions/delete-database-record';
import { findDatabaseRecord } from './lib/actions/find-database-record';
import { updateDatabaseRecord } from './lib/actions/update-database-record';
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import { BASE_URL } from './lib/common/client';
import { PieceCategory } from '@activepieces/shared';
import { newDatabaseRecord } from './lib/triggers/new-database-record';
export const softr = createPiece({
displayName: 'Softr',
auth: SoftrAuth,
minimumSupportedRelease: '0.36.1',
logoUrl: 'https://cdn.activepieces.com/pieces/softr.png',
categories:[PieceCategory.CONTENT_AND_FILES,PieceCategory.PRODUCTIVITY],
authors: ['Sanket6652'],
actions: [
createAppUser,
createDatabaseRecord,
deleteAppUser,
deleteDatabaseRecord,
findDatabaseRecord,
updateDatabaseRecord,
createCustomApiCallAction({
auth:SoftrAuth,
baseUrl:()=>BASE_URL,
authMapping:async (auth)=>{
return{
'Softr-Api-Key':auth.secret_text
}
}
})
],
triggers: [newDatabaseRecord],
});

View File

@@ -0,0 +1,74 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
export const createAppUser = createAction({
auth: SoftrAuth,
name: 'createAppUser',
displayName: 'Create App User',
description: 'Creates a new user inside a Softr app.',
props: {
email: Property.ShortText({
displayName: 'Email',
description: 'The email address of the new user.',
required: true,
}),
full_name: Property.ShortText({
displayName: 'Name',
description: 'The full name of the new user.',
required: true,
}),
password: Property.ShortText({
displayName: 'Password',
description: 'The password for the new user.',
required: true,
}),
domain: Property.ShortText({
displayName: 'Domain',
description:
'The domain or subdomain of the Softr app where the user will be created.',
required: true,
}),
generate_magic_link: Property.Checkbox({
displayName: 'Generate Magic Link',
description: 'If checked, a magic link will be generated for the user.',
required: false,
defaultValue: false,
}),
},
async run({ auth, propsValue }) {
const { email, full_name, password, generate_magic_link, domain } =
propsValue;
// Build the request body
const requestBody: any = {
email,
full_name,
password,
generate_magic_link,
};
try {
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: `https://studio-api.softr.io/v1/api/users`,
headers: {
'Softr-Api-Key': auth.secret_text,
'Softr-Domain': domain,
'Content-Type': 'application/json',
},
body: requestBody,
});
return {
success: true,
user: response,
message: 'User created successfully',
};
} catch (error: any) {
throw new Error(
`Failed to create user: ${error.message || String(error)}`
);
}
},
});

View File

@@ -0,0 +1,51 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
import { makeRequest, transformRecordFields } from '../common/client';
import { databaseIdDropdown, tableFields, tableIdDropdown } from '../common/props';
import { isNil } from '@activepieces/shared';
import { TableField } from '../common/types';
export const createDatabaseRecord = createAction({
auth: SoftrAuth,
name: 'createDatabaseRecord',
displayName: 'Create Database Record',
description: 'Creates a new record.',
props: {
databaseId: databaseIdDropdown,
tableId: tableIdDropdown,
fields: tableFields,
},
async run({ auth, propsValue }) {
const { databaseId, tableId } = propsValue;
const fields = propsValue.fields ?? {};
const formattedFields: Record<string, any> = {};
for (const [key, value] of Object.entries(fields)) {
if (isNil(value) || value === '') continue;
if (Array.isArray(value) && value.length === 0) continue;
formattedFields[key] = value;
}
const response = await makeRequest<{
data: { id: string; createdAt: string; updatedAt: string; fields: Record<string, any> };
}>(auth, HttpMethod.POST, `/databases/${databaseId}/tables/${tableId}/records`, {
fields: formattedFields,
});
const tableReponse = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
const transformedFields = transformRecordFields(tableReponse.data.fields, response.data.fields);
return {
...response.data,
fields: transformedFields,
};
},
});

View File

@@ -0,0 +1,51 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
export const deleteAppUser = createAction({
auth: SoftrAuth,
name: 'deleteAppUser',
displayName: 'Delete App User',
description: 'Deletes a user from a Softr app.',
props: {
email: Property.ShortText({
displayName: 'User Email',
description: 'The email address of the user to delete.',
required: true,
}),
domain: Property.ShortText({
displayName: 'Softr Domain',
description: 'The domain or subdomain of the Softr app (e.g., yourdomain.com or subdomain.softr.app).',
required: true,
}),
},
async run({ auth, propsValue }) {
const { email, domain } = propsValue;
try {
const response = await httpClient.sendRequest({
method: HttpMethod.DELETE,
url: `https://studio-api.softr.io/v1/api/users/${encodeURIComponent(email)}`,
headers: {
'Softr-Api-Key': auth.secret_text,
'Softr-Domain': domain,
'Content-Type': 'application/json',
},
});
return {
success: true,
message: `User ${email} deleted successfully from ${domain}`,
statusCode: response.status,
};
} catch (error: any) {
if (error.response?.status === 404) {
throw new Error(`User with email ${email} not found in app ${domain}`);
} else if (error.response?.status === 403) {
throw new Error(`Access denied. Check your API key and domain permissions`);
} else {
throw new Error(`Failed to delete user: ${error.message || String(error)}`);
}
}
},
});

View File

@@ -0,0 +1,36 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
import { makeRequest } from '../common/client';
import {
databaseIdDropdown,
recordIdField,
tableIdDropdown,
} from '../common/props';
export const deleteDatabaseRecord = createAction({
auth: SoftrAuth,
name: 'deleteDatabaseRecord',
displayName: 'Delete Database Record',
description: 'Deletes a existing database record.',
props: {
databaseId: databaseIdDropdown,
tableId: tableIdDropdown,
recordId: recordIdField,
},
async run({ auth, propsValue }) {
const { databaseId, tableId, recordId } = propsValue;
const response = await makeRequest(
auth,
HttpMethod.DELETE,
`/databases/${databaseId}/tables/${tableId}/records/${recordId}`
);
return {
success: true,
message: 'Record deleted successfully',
recordId: recordId,
};
},
});

View File

@@ -0,0 +1,79 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
import { makeRequest, transformRecordFields } from '../common/client';
import { databaseIdDropdown, tableFieldIdDropdown, tableIdDropdown } from '../common/props';
import { TableField } from '../common/types';
export const findDatabaseRecord = createAction({
auth: SoftrAuth,
name: 'findDatabaseRecord',
displayName: 'Find Database Record',
description: 'Finds a record in table.',
props: {
databaseId: databaseIdDropdown,
tableId: tableIdDropdown,
fieldId: tableFieldIdDropdown,
fieldValue: Property.ShortText({
displayName: 'Field Value',
required: true,
}),
},
async run({ auth, propsValue }) {
const { databaseId, tableId, fieldId, fieldValue } = propsValue;
const requestBody = {
paging: {
limit: 1,
},
filter: {
condition: {
operator: 'AND',
conditions: [
{
leftSide: fieldId,
operator: 'IS',
rightSide: fieldValue,
},
],
},
},
};
const response = await makeRequest<{
data: {
fields: TableField[];
}[];
}>(
auth,
HttpMethod.POST,
`/databases/${databaseId}/tables/${tableId}/records/search`,
requestBody,
);
if (Array.isArray(response.data) && response.data.length === 0) {
return {
found: false,
data: {},
};
}
const foundRecord = response.data[0];
const tableReponse = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
const transformedFields = transformRecordFields(tableReponse.data.fields, foundRecord.fields);
return {
found: true,
data: {
...foundRecord,
fields: transformedFields,
},
};
},
});

View File

@@ -0,0 +1,52 @@
import { createAction } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { SoftrAuth } from '../common/auth';
import { makeRequest, transformRecordFields } from '../common/client';
import { databaseIdDropdown, recordIdField, tableFields, tableIdDropdown } from '../common/props';
import { isNil } from '@activepieces/shared';
import { TableField } from '../common/types';
export const updateDatabaseRecord = createAction({
auth: SoftrAuth,
name: 'updateDatabaseRecord',
displayName: 'Update Database Record',
description: 'Updates an existing database record.',
props: {
databaseId: databaseIdDropdown,
tableId: tableIdDropdown,
recordId: recordIdField,
fields: tableFields,
},
async run({ auth, propsValue }) {
const { databaseId, tableId, recordId } = propsValue;
const fields = propsValue.fields ?? {};
const formattedFields: Record<string, any> = {};
for (const [key, value] of Object.entries(fields)) {
if (isNil(value) || value === '') continue;
if (Array.isArray(value) && value.length === 0) continue;
formattedFields[key] = value;
}
const response = await makeRequest<{
data: { id: string; createdAt: string; updatedAt: string; fields: Record<string, any> };
}>(auth, HttpMethod.PATCH, `/databases/${databaseId}/tables/${tableId}/records/${recordId}`, {
fields: formattedFields,
});
const tableReponse = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
const transformedFields = transformRecordFields(tableReponse.data.fields, response.data.fields);
return {
...response.data,
fields: transformedFields,
};
},
});

View File

@@ -0,0 +1,32 @@
import { PieceAuth } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { makeRequest } from './client';
import { AppConnectionType } from '@activepieces/shared';
export const SoftrAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: `You can obtain your API key from [API Settings](https://studio.softr.io/user/apisettings).`,
required: true,
validate: async ({ auth }) => {
if (auth) {
try {
await makeRequest({
secret_text: auth,
type: AppConnectionType.SECRET_TEXT,
}, HttpMethod.GET, '/databases');
return {
valid: true,
};
} catch (error) {
return {
valid: false,
error: 'Invalid API Key',
};
}
}
return {
valid: false,
error: 'Invalid API Key',
};
},
});

View File

@@ -0,0 +1,49 @@
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
import { TableField } from './types';
import { AppConnectionValueForAuthProperty } from '@activepieces/pieces-framework';
import { SoftrAuth } from './auth';
export const BASE_URL = `https://tables-api.softr.io/api/v1`;
export async function makeRequest<T>(
api_key: AppConnectionValueForAuthProperty<typeof SoftrAuth>,
method: HttpMethod,
path: string,
body?: unknown
) {
try {
const response = await httpClient.sendRequest<T>({
method,
url: `${BASE_URL}${path}`,
headers: {
'Softr-Api-Key': api_key.secret_text,
'Content-Type': 'application/json',
},
body,
});
return response.body;
} catch (error: any) {
throw new Error(`Unexpected error: ${error.message || String(error)}`);
}
}
export function transformRecordFields(
tableFields: TableField[],
tableValues: Record<string, any>,
)
{
const fieldMap: Record<string, string> = tableFields.reduce((acc, field) => {
acc[field.id] = field.name;
return acc;
}, {} as Record<string, string>);
const transformedFields: Record<string, any> = {};
for (const [key, value] of Object.entries(tableValues)) {
const label = fieldMap[key] ?? key;
transformedFields[label] = value;
}
return transformedFields;
}

View File

@@ -0,0 +1,225 @@
import { DynamicPropsValue, Property } from '@activepieces/pieces-framework';
import { makeRequest } from './client';
import { HttpMethod } from '@activepieces/pieces-common';
import { TableField } from './types';
import { SoftrAuth } from './auth';
export const databaseIdDropdown = Property.Dropdown({
auth: SoftrAuth,
displayName: 'Database ID',
description: 'Select the database to insert the record into',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account first',
};
}
try {
const databases = await makeRequest<{
data: { id: string; name: string }[];
}>(auth, HttpMethod.GET, '/databases');
return {
disabled: false,
options: databases.data.map((database) => ({
label: database.name,
value: database.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading teams',
};
}
},
});
export const tableIdDropdown = Property.Dropdown({
displayName: 'Table ID',
description: 'Select the table to insert the record into',
required: true,
refreshers: ['auth', 'databaseId'],
auth: SoftrAuth,
options: async ({ auth, databaseId }) => {
if (!auth || !databaseId) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account and select a database first',
};
}
try {
const tables = await makeRequest<{
data: { id: string; name: string }[];
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables`);
return {
disabled: false,
options: tables.data.map((table) => ({
label: table.name,
value: table.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading tables',
};
}
},
});
export const recordIdField = Property.ShortText({
displayName: 'Record ID',
required: true,
});
export const tableFieldIdDropdown = Property.Dropdown({
displayName:'Field',
refreshers: ['auth', 'databaseId', 'tableId'],
auth: SoftrAuth,
required:true,
options:async ({auth,databaseId,tableId})=>{
if (!auth || !databaseId || !tableId) {
return {
disabled: true,
options: [],
placeholder: 'Please connect your account and select a table first.',
};
}
try {
const response = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
return {
disabled: false,
options: response.data.fields.map((field) => ({
label: field.name,
value: field.id,
})),
};
} catch (error) {
return {
disabled: true,
options: [],
placeholder: 'Error loading Fields.',
};
}
}
})
export const tableFields = Property.DynamicProperties({
displayName: 'Fields',
required: true,
refreshers: ['auth', 'databaseId', 'tableId'],
auth: SoftrAuth,
props: async ({ auth, databaseId, tableId }) => {
if (!databaseId || !tableId||!auth) {
return {};
}
try {
const response = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
const tableData = response.data || response;
const fields = tableData.fields || [];
const dynamicProps: DynamicPropsValue = {};
fields.forEach((field) => {
// Skip readonly fields
if (field.readonly) {
return;
}
const fieldId = field.id;
const fieldName = field.name || fieldId;
const fieldType = field.type;
const isRequired = false;
switch (fieldType) {
case 'SINGLE_LINE_TEXT':
case 'EMAIL':
case 'URL':
case 'PHONE':
dynamicProps[fieldId] = Property.ShortText({
displayName: fieldName,
required: isRequired,
});
break;
case 'SELECT': {
const options = field.options.choices
? field.options.choices.map((option) => ({
label: option.label,
value: option.id,
}))
: [];
dynamicProps[fieldId] = field.allowMultipleEntries
? Property.StaticMultiSelectDropdown({
displayName: fieldName,
required: isRequired,
options: { options },
})
: Property.StaticDropdown({
displayName: fieldName,
required: isRequired,
options: { options },
});
break;
}
case 'LONG_TEXT':
dynamicProps[fieldId] = Property.LongText({
displayName: fieldName,
required: isRequired,
});
break;
case 'NUMBER':
case 'CURRENCY':
case 'PERCENT':
case 'RATING':
dynamicProps[fieldId] = Property.Number({
displayName: fieldName,
required: isRequired,
});
break;
case 'CHECKBOX':
dynamicProps[fieldId] = Property.Checkbox({
displayName: fieldName,
required: isRequired,
});
break;
case 'DATETIME':
dynamicProps[fieldId] = Property.DateTime({
displayName: fieldName,
required: isRequired,
});
break;
default:
break;
}
});
return dynamicProps;
} catch (error) {
console.error('Error fetching table fields:', error);
return {};
}
},
});

View File

@@ -0,0 +1,10 @@
export interface TableField {
id: string;
name: string;
type: string;
readonly: boolean;
allowMultipleEntries: boolean;
options: {
choices?: { id: string; label: string }[];
};
}

View File

@@ -0,0 +1,102 @@
import { AppConnectionValueForAuthProperty, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
import { DedupeStrategy, Polling, pollingHelper, HttpMethod } from '@activepieces/pieces-common';
import dayjs from 'dayjs';
import { SoftrAuth } from '../common/auth';
import { makeRequest, transformRecordFields } from '../common/client';
import { databaseIdDropdown, tableIdDropdown } from '../common/props';
import { TableField } from '../common/types';
type Props = {
databaseId: string;
tableId: string;
};
const polling: Polling<AppConnectionValueForAuthProperty<typeof SoftrAuth>, Props> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
const { databaseId, tableId } = propsValue;
let offset = 0;
let hasMore = true;
const isTest = lastFetchEpochMS === 0;
const result = [];
let count = 0;
do {
const response = await makeRequest<{
data: { createdAt: string; fields: Record<string, any> }[];
}>(
auth,
HttpMethod.GET,
`/databases/${databaseId}/tables/${tableId}/records?limit=100&offset=${offset}`,
);
const items = response.data ?? [];
result.push(...items);
if (isTest) break;
hasMore = items.length > 0;
offset += 100;
count++;
} while (hasMore);
console.log('COUNT',count)
const tableReponse = await makeRequest<{
data: {
fields: TableField[];
};
}>(auth, HttpMethod.GET, `/databases/${databaseId}/tables/${tableId}`);
return result.map((record) => {
const transformedFields = transformRecordFields(tableReponse.data.fields, record.fields);
return {
epochMilliSeconds: dayjs(record.createdAt).valueOf(),
data: {
...record,
fields: transformedFields,
},
};
});
},
};
export const newDatabaseRecord = createTrigger({
auth: SoftrAuth,
name: 'newDatabaseRecord',
displayName: 'New Database Record',
description: 'Triggers when a new record is added.',
props: {
databaseId: databaseIdDropdown,
tableId: tableIdDropdown,
},
sampleData: {
id: 'rec123456',
fields: {
created_date: '2025-08-01T10:00:00Z',
field1: 'Sample Value',
field2: 'Another Value',
},
},
type: TriggerStrategy.POLLING,
async test(context) {
const { store, auth, propsValue, files } = context;
return await pollingHelper.test(polling, { store, auth, propsValue, files });
},
async onEnable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onEnable(polling, { store, auth, propsValue });
},
async onDisable(context) {
const { store, auth, propsValue } = context;
await pollingHelper.onDisable(polling, { store, auth, propsValue });
},
async run(context) {
const { store, auth, propsValue, files } = context;
return await pollingHelper.poll(polling, { store, auth, propsValue, files });
},
});

View File

@@ -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"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"]
}