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,18 @@
{
"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 @@
# pieces-microsoft-dynamics-crm

View File

@@ -0,0 +1,4 @@
{
"name": "@activepieces/piece-microsoft-dynamics-crm",
"version": "0.1.13"
}

View File

@@ -0,0 +1,57 @@
{
"name": "pieces-microsoft-dynamics-crm",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/microsoft-dynamics-crm/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/microsoft-dynamics-crm",
"tsConfig": "packages/pieces/community/microsoft-dynamics-crm/tsconfig.lib.json",
"packageJson": "packages/pieces/community/microsoft-dynamics-crm/package.json",
"main": "packages/pieces/community/microsoft-dynamics-crm/src/index.ts",
"assets": [
"packages/pieces/community/microsoft-dynamics-crm/*.md",
{
"input": "packages/pieces/community/microsoft-dynamics-crm/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"publish": {
"command": "node tools/scripts/publish.mjs pieces-microsoft-dynamics-crm {args.ver} {args.tag}",
"dependsOn": [
"build"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/microsoft-dynamics-crm",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
}
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Customer Relationship Management Softwarepaket entwickelt von Microsoft.",
"Host URL (without trailing slash)": "Host-URL (ohne Schrägstrich)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "Proxy-URL mit Port",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host-URL ohne Slash.Zum Beispiel **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "Dies finden Sie im Azure Portal.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Bleiben Sie leer, wenn nicht nötig. Optionale Proxy-URL, die zur Herstellung von Verbindungen verwendet wird, wenn Proxy-Anfragen benötigt werden. Zum Beispiel: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Melden Sie sich bei [Microsoft Azure Portal](https://portal.azure.com/).\n2. Von der linken Seitenleiste gehen Sie zur **Microsoft Enfra ID**.\n3. Unter **Verwalten** klicken Sie auf **App-Registrierungen**.\n4. Klicken Sie auf die **Neue Registrierung** Schaltfläche.\n5. Geben Sie einen **Name** für Ihre App ein.\n6. Für **unterstützte Kontotypen**, auswählen:\n - **Konten in jedem Organisationsverzeichnis (jeder Microsoft-Entra-ID-Mieter - Multitenant) und persönlichen Microsoft-Konten**\n - Oder wählen Sie nach Ihren Anforderungen aus.\n7. In **Umleitungs-URI** wählen Sie **Web** und fügen Sie die angegebene URL hinzu.\n8. Klicken Sie auf **Registrieren**.\n9. Nach der Registrierung werden Sie zur Übersichtsseite der App weitergeleitet. Kopieren Sie die **Anwendungs-(Client)-ID**.\n10. Vom linken Menü gehen Sie zu **Zertifikate & Geheimnisse**.\n - Unter **Kundengeheimnis**, klicke **Neues Kundengeheimnis**.\n - Geben Sie eine Beschreibung an, setzen Sie ein Ablaufdatum und klicken Sie auf **Hinzufügen**.\n - Kopieren Sie den **Wert** des Client-Geheimnisses (dies wird nicht wieder angezeigt).\n11. Gehe zu **API Berechtigungen** vom linken Menü.\n - Klicke **Berechtigung hinzufügen**.\n - Wähle **Dynamics CRM** → **Delegierte Berechtigungen**.\n - Klicke **Berechtigungen hinzufügen**.\n12. Kopieren Sie Ihre **Client-ID** und **Client-Geheimnis**.\n",
"Create Record": "Datensatz erstellen",
"Delete Record": "Datensatz löschen",
"Get Record": "Datensatz abrufen",
"Update Record": "Datensatz aktualisieren",
"Custom API Call": "Eigener API-Aufruf",
"Creates a new record.": "Erstellt einen neuen Datensatz.",
"Deletes an existing record.": "Löscht einen existierenden Eintrag.",
"Retrieves an existing record.": "Ruft einen vorhandenen Datensatz ab.",
"Updates an existing record.": "Aktualisiert einen existierenden Datensatz.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Entity Type": "Entitätstyp",
"Entity Fields": "Entitäts-Felder",
"Record ID": "Datensatz-ID",
"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)",
"Select or map the entity for which you want to create the record.": "Wählen Sie die Entität aus für die Sie den Datensatz erstellen möchten.",
"Select or map the entity name whose records you want to delete.": "Wählen Sie den Entitätsnamen aus, dessen Datensätze Sie löschen möchten.",
"Select or map the entity name whose records you want to retrieve.": "Wählen Sie den Entitätsnamen aus, dessen Datensätze Sie abfragen möchten.",
"Select or map the entity for which you want to update the record.": "Wählen Sie die Entität aus für die Sie den Datensatz aktualisieren möchten.",
"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"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Paquete de software de gestión de relaciones con el cliente desarrollado por Microsoft.",
"Host URL (without trailing slash)": "URL del host (sin barra final)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "URL del proxy con puerto",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "URL del host sin slash.Por ejemplo **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "Puede encontrarlo en el portal Azure.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Dejar vacío si no es necesario. URL opcional del proxy usada para establecer conexiones cuando se necesitan peticiones de proxy. Por ejemplo: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and add the given URL.\n8. Click **Register**.\n9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.\n10. From the left menu, go to **Certificates & secrets**.\n - Under **Client secrets**, click **New client secret**.\n - Provide a description, set an expiry, and click **Add**.\n - Copy the **Value** of the client secret (this will not be shown again).\n11. Go to **API permissions** from the left menu.\n - Click **Add a permission**.\n - Select **Dynamics CRM** → **Delegated permissions**.\n - Click **Add permissions**.\n12. Copy your **Client ID** and **Client Secret**.\n",
"Create Record": "Crear registro",
"Delete Record": "Eliminar registro",
"Get Record": "Obtener registro",
"Update Record": "Actualizar registro",
"Custom API Call": "Llamada API personalizada",
"Creates a new record.": "Crea un nuevo registro.",
"Deletes an existing record.": "Elimina un registro existente.",
"Retrieves an existing record.": "Obtiene un registro existente.",
"Updates an existing record.": "Actualiza un registro existente.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Entity Type": "Tipo de entidad",
"Entity Fields": "Campos de Entidad",
"Record ID": "ID de registro",
"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)",
"Select or map the entity for which you want to create the record.": "Seleccione o mapee la entidad para la que desea crear el registro.",
"Select or map the entity name whose records you want to delete.": "Seleccione o mapee el nombre de la entidad cuyos registros desea eliminar.",
"Select or map the entity name whose records you want to retrieve.": "Seleccione o mapee el nombre de la entidad cuyos registros desea recuperar.",
"Select or map the entity for which you want to update the record.": "Seleccione o mapee la entidad para la que desea actualizar el registro.",
"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"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Ensemble de logiciels de gestion de la relation client développé par Microsoft.",
"Host URL (without trailing slash)": "URL de l'hôte (sans slash de fin de ligne)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "URL du proxy avec port",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "URL de l'hôte sans slash.Par exemple **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "Vous pouvez le trouver sur le portail Azure.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Laisser vide si ce n'est pas nécessaire. URL de proxy optionnelle utilisée pour établir des connexions lorsque des requêtes de proxy sont nécessaires. Par exemple : **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and add the given URL.\n8. Click **Register**.\n9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.\n10. From the left menu, go to **Certificates & secrets**.\n - Under **Client secrets**, click **New client secret**.\n - Provide a description, set an expiry, and click **Add**.\n - Copy the **Value** of the client secret (this will not be shown again).\n11. Go to **API permissions** from the left menu.\n - Click **Add a permission**.\n - Select **Dynamics CRM** → **Delegated permissions**.\n - Click **Add permissions**.\n12. Copy your **Client ID** and **Client Secret**.\n",
"Create Record": "Créer un enregistrement",
"Delete Record": "Supprimer l'enregistrement",
"Get Record": "Obtenir un enregistrement",
"Update Record": "Mettre à jour l'enregistrement",
"Custom API Call": "Appel API personnalisé",
"Creates a new record.": "Crée un nouvel enregistrement.",
"Deletes an existing record.": "Supprime un enregistrement existant.",
"Retrieves an existing record.": "Récupère un enregistrement existant.",
"Updates an existing record.": "Met à jour un enregistrement existant.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
"Entity Type": "Type d'entité",
"Entity Fields": "Champs d'Entité",
"Record ID": "ID de l'enregistrement",
"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'attente (en secondes)",
"Select or map the entity for which you want to create the record.": "Sélectionnez ou associez l'entité pour laquelle vous voulez créer l'enregistrement.",
"Select or map the entity name whose records you want to delete.": "Sélectionnez ou associez le nom de l'entité dont vous souhaitez supprimer les enregistrements.",
"Select or map the entity name whose records you want to retrieve.": "Sélectionnez ou associez le nom de l'entité dont vous souhaitez récupérer les enregistrements.",
"Select or map the entity for which you want to update the record.": "Sélectionnez ou associez l'entité pour laquelle vous souhaitez mettre à jour l'enregistrement.",
"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": "OBTENIR",
"POST": "POSTER",
"PATCH": "PATCH",
"PUT": "EFFACER",
"DELETE": "SUPPRIMER",
"HEAD": "TÊTE"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Microsoftが開発した顧客関係管理ソフトウェアパッケージ。",
"Host URL (without trailing slash)": "ホスト URL (末尾のスラッシュなし)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "ポート付きプロキシURL",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "スラッシュの末尾のないホストURL。例えば **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "これは Azure ポータルで確認できます。",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "不要な場合は空のままにしておきます。プロキシのリクエストが必要なときに接続を確立するためのオプションのプロキシ URL です。例: **https://proxy.com:8080**",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and add the given URL.\n8. Click **Register**.\n9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.\n10. From the left menu, go to **Certificates & secrets**.\n - Under **Client secrets**, click **New client secret**.\n - Provide a description, set an expiry, and click **Add**.\n - Copy the **Value** of the client secret (this will not be shown again).\n11. Go to **API permissions** from the left menu.\n - Click **Add a permission**.\n - Select **Dynamics CRM** → **Delegated permissions**.\n - Click **Add permissions**.\n12. Copy your **Client ID** and **Client Secret**.\n",
"Create Record": "レコードを作成",
"Delete Record": "レコードを削除",
"Get Record": "レコードを取得",
"Update Record": "更新記録",
"Custom API Call": "カスタムAPI通話",
"Creates a new record.": "新規レコードを作成",
"Deletes an existing record.": "既存のレコードを削除します。",
"Retrieves an existing record.": "既存のレコードを取得します。",
"Updates an existing record.": "既存のレコードを更新します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Entity Type": "エンティティタイプ",
"Entity Fields": "エンティティフィールド",
"Record ID": "レコードID",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Select or map the entity for which you want to create the record.": "レコードを作成するエンティティを選択またはマップします。",
"Select or map the entity name whose records you want to delete.": "レコードを削除するエンティティ名を選択またはマップします。",
"Select or map the entity name whose records you want to retrieve.": "レコードを取得するエンティティ名を選択またはマップします。",
"Select or map the entity for which you want to update the record.": "レコードを更新するエンティティを選択またはマップします。",
"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": "頭"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Pakket software ontwikkeld door Microsoft.",
"Host URL (without trailing slash)": "URL van de host (zonder slash)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "ProxyURL met poort",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host URL zonder slash.Bijvoorbeeld **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "U vindt dit in het Azure portaal.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Laat leeg indien niet nodig. Optionele proxy URL gebruikt voor het instellen van verbindingen wanneer proxyverzoeken nodig zijn. Bijvoorbeeld: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Log in bij [Microsoft Azure Portal](https://portal.azure.com/).\n2. Ga naar **Microsoft Enfra ID**.\n3. Onder **Beheren**, klik op **App registraties**.\n4. Klik op de **Nieuwe registratie** knop.\n5. Voer een **Naam** in voor uw app.\n6. Voor **Ondersteunde accounttypen**, kies keuze:\n - **Accounts in elke map van de organisatie (Any Microsoft Entra ID-tenant - Multitenant) en persoonlijke Microsoft accounts**\n - Of selecteer gebaseerd op uw vereiste.\n7. In **Redirect URI**, selecteer **Web** en voeg de opgegeven URL toe.\n8. Klik **Register**.\n9. Na registratie wordt u doorverwezen naar de overzichtspagina. Kopieer de **Applicatie (client) ID**.\n10. Vanuit het linkermenu ga naar **Certificaten en geheimen**.\n - Klik onder **Client geheimen** op **Nieuwe client geheim**.\n - Geef een beschrijving, verloop, en klik **Toevoegen**.\n - Kopieer de **Waarde** van de client secret (dit zal niet meer worden getoond).\n11. Ga naar **API-rechten** vanuit het linkermenu.\n - Klik **Een machtiging toevoegen**.\n - Selecteer **Dynamics CRM** → **Toegewezen machtigingen**.\n - Klik **Permissies toevoegen**.\n12. Kopieer de **Client ID** en **Client Secret**.\n",
"Create Record": "Record Maken",
"Delete Record": "Record verwijderen",
"Get Record": "Krijg Record",
"Update Record": "Update Record",
"Custom API Call": "Custom API Call",
"Creates a new record.": "Maakt een nieuw record aan.",
"Deletes an existing record.": "Verwijdert een bestaand record.",
"Retrieves an existing record.": "Ophalen van een bestaand record.",
"Updates an existing record.": "Werkt een bestaand record bij.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Entity Type": "Entiteit type",
"Entity Fields": "Entiteit velden",
"Record ID": "Record ID",
"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)",
"Select or map the entity for which you want to create the record.": "Selecteer of kaart de entiteit waarvoor u de record wilt aanmaken.",
"Select or map the entity name whose records you want to delete.": "Selecteer of wijs de entiteitsnaam toe waarvan u de records wilt verwijderen.",
"Select or map the entity name whose records you want to retrieve.": "Selecteer of wijs de entiteitsnaam toe waarvan u de records wilt ophalen.",
"Select or map the entity for which you want to update the record.": "Selecteer of kaart de entiteit waarvoor u de record wilt bijwerken.",
"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"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Pacote de software de gerenciamento de clientes desenvolvido pela Microsoft.",
"Host URL (without trailing slash)": "Host URL (sem barra à direita)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "URL do Proxy com Porta",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host URL sem trailing slash.Por exemplo **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "Pode encontrar isso no portal Azure .",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Manter vazio se não necessário. URL de proxy opcional usada para estabelecer conexões quando requisições de proxy é necessário. Por exemplo: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Entre no [Microsoft Azure Portal](https://portal.azure.com/).\n2. Na barra lateral esquerda, vá até **Microsoft Enfra ID**.\n3. Sob **Gerenciar**, clique em **Aplicativos registrados**.\n4. Clique no botão **Novo registro**.\n5. Digite um **Nome** para o seu aplicativo.\n6. Para **Tipos de conta suportados**, escolha:\n - **Contas em qualquer diretório organizacional (qualquer inquilino de ID da Microsoft Entra - Multitenant) e contas pessoais da Microsoft**\n - Ou selecione com base nos seus requisitos.\n7. Em **URI de redirecionamento**, selecione **Web** e adicione a URL fornecida.\n8. Clique em **Registrar**.\n9. Após o registro, você será redirecionado para a página de visão geral do aplicativo. Copie o **ID do aplicativo (cliente) **.\n10. No menu à esquerda, vá para **Certificados e segredos**.\n - Em **Segredos do Cliente**, clique em **Novo segredo do Cliente**.\n - Fornece uma descrição, define um vencimento e clique em **Adicionar**.\n - Copiar o **Valor** do segredo do cliente (não será mostrado novamente).\n11. Vá para **Permissões da API** no menu à esquerda.\n - Clique em **Adicionar permissão**.\n - Selecione **Dinâmica CRM** → **Delegated permissions**.\n - Clique em **Adicionar permissões**.\n12. Copie seu **ID do Cliente** e **Segredo do Cliente**.\n",
"Create Record": "Criar Registro",
"Delete Record": "Excluir registro",
"Get Record": "Obter Registro",
"Update Record": "Atualizar Registro",
"Custom API Call": "Chamada de API personalizada",
"Creates a new record.": "Cria um novo registro.",
"Deletes an existing record.": "Exclui um registro existente.",
"Retrieves an existing record.": "Recupera um registro existente.",
"Updates an existing record.": "Atualiza um registro existente.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Entity Type": "Tipo de entidade",
"Entity Fields": "Campos de Entidade",
"Record ID": "ID do Registro",
"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)",
"Select or map the entity for which you want to create the record.": "Selecione ou mapeie a entidade para a qual você deseja criar o registro.",
"Select or map the entity name whose records you want to delete.": "Selecione ou mapeie o nome da entidade cujos registros você deseja apagar.",
"Select or map the entity name whose records you want to retrieve.": "Selecione ou mapeie o nome da entidade cujos registros você deseja recuperar.",
"Select or map the entity for which you want to update the record.": "Selecione ou mapeie a entidade para a qual você deseja atualizar o registro.",
"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"
}

View File

@@ -0,0 +1,40 @@
{
"Microsoft Dynamics CRM": "Microsoft Dynamics CRM",
"Customer relationship management software package developed by Microsoft.": "Программный пакет управления связями с клиентами, разработанный компанией Microsoft.",
"Host URL (without trailing slash)": "URL хоста (без слеша в конце)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "URL прокси с портом",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "URL хоста без trailing slash.Например **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "Вы можете найти это на портале Azure.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Оставьте пустым, если это не нужно. Необязательный URL-адрес прокси-сервера используется для установки соединений при запросе прокси-сервера. Например: **https://proxy.com:8080**.",
"Create Record": "Создать запись",
"Delete Record": "Удалить запись",
"Get Record": "Получить запись",
"Update Record": "Обновить запись",
"Custom API Call": "Пользовательский вызов API",
"Creates a new record.": "Создает новую запись.",
"Deletes an existing record.": "Удалить существующую запись.",
"Retrieves an existing record.": "Извлекает существующую запись.",
"Updates an existing record.": "Обновление существующей записи.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Entity Type": "Тип сущности",
"Entity Fields": "Поля сущностей",
"Record ID": "ID записи",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Select or map the entity for which you want to create the record.": "Выберите или сопоставьте объект, для которого вы хотите создать запись.",
"Select or map the entity name whose records you want to delete.": "Выберите или привяжите имя сущности, чьи записи вы хотите удалить.",
"Select or map the entity name whose records you want to retrieve.": "Выберите или привяжите имя сущности, чьи записи вы хотите получить.",
"Select or map the entity for which you want to update the record.": "Выберите или укажите объект, для которого вы хотите обновить запись.",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Customer relationship management software package developed by Microsoft.",
"Host URL (without trailing slash)": "Host URL (without trailing slash)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "Proxy URL with Port",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host URL without trailing slash.For example **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "You can find this in the Azure portal.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and add the given URL.\n8. Click **Register**.\n9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.\n10. From the left menu, go to **Certificates & secrets**.\n - Under **Client secrets**, click **New client secret**.\n - Provide a description, set an expiry, and click **Add**.\n - Copy the **Value** of the client secret (this will not be shown again).\n11. Go to **API permissions** from the left menu.\n - Click **Add a permission**.\n - Select **Dynamics CRM** → **Delegated permissions**.\n - Click **Add permissions**.\n12. Copy your **Client ID** and **Client Secret**.\n",
"Create Record": "Create Record",
"Delete Record": "Delete Record",
"Get Record": "Get Record",
"Update Record": "Update Record",
"Custom API Call": "Custom API Call",
"Creates a new record.": "Creates a new record.",
"Deletes an existing record.": "Deletes an existing record.",
"Retrieves an existing record.": "Retrieves an existing record.",
"Updates an existing record.": "Updates an existing record.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Entity Type": "Entity Type",
"Entity Fields": "Entity Fields",
"Record ID": "Record ID",
"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)",
"Select or map the entity for which you want to create the record.": "Select or map the entity for which you want to create the record.",
"Select or map the entity name whose records you want to delete.": "Select or map the entity name whose records you want to delete.",
"Select or map the entity name whose records you want to retrieve.": "Select or map the entity name whose records you want to retrieve.",
"Select or map the entity for which you want to update the record.": "Select or map the entity for which you want to update the record.",
"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"
}

View File

@@ -0,0 +1,40 @@
{
"Microsoft Dynamics CRM": "Microsoft Dynamics CRM",
"Customer relationship management software package developed by Microsoft.": "Customer relationship management software package developed by Microsoft.",
"Host URL (without trailing slash)": "Host URL (without trailing slash)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "Proxy URL with Port",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host URL without trailing slash.For example **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "You can find this in the Azure portal.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.",
"Create Record": "Create Record",
"Delete Record": "Delete Record",
"Get Record": "Get Record",
"Update Record": "Update Record",
"Custom API Call": "Custom API Call",
"Creates a new record.": "Creates a new record.",
"Deletes an existing record.": "Deletes an existing record.",
"Retrieves an existing record.": "Retrieves an existing record.",
"Updates an existing record.": "Updates an existing record.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Entity Type": "Entity Type",
"Entity Fields": "Entity Fields",
"Record ID": "Record ID",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Select or map the entity for which you want to create the record.": "Select or map the entity for which you want to create the record.",
"Select or map the entity name whose records you want to delete.": "Select or map the entity name whose records you want to delete.",
"Select or map the entity name whose records you want to retrieve.": "Select or map the entity name whose records you want to retrieve.",
"Select or map the entity for which you want to update the record.": "Select or map the entity for which you want to update the record.",
"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"
}

View File

@@ -0,0 +1,42 @@
{
"Customer relationship management software package developed by Microsoft.": "Customer relationship management software package developed by Microsoft.",
"Host URL (without trailing slash)": "Host URL (without trailing slash)",
"Tenant ID": "Tenant ID",
"Proxy URL with Port": "Proxy URL with Port",
"Host URL without trailing slash.For example **https://demo.crm.dynamics.com**": "Host URL without trailing slash.For example **https://demo.crm.dynamics.com**",
"You can find this in the Azure portal.": "You can find this in the Azure portal.",
"Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.": "Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.",
"\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and ad": "\n1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).\n2. From the left sidebar, go to **Microsoft Enfra ID**.\n3. Under **Manage**, click on **App registrations**.\n4. Click the **New registration** button.\n5. Enter a **Name** for your app.\n6. For **Supported account types**, choose:\n - **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**\n - Or select based on your requirement.\n7. In **Redirect URI**, select **Web** and add the given URL.\n8. Click **Register**.\n9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.\n10. From the left menu, go to **Certificates & secrets**.\n - Under **Client secrets**, click **New client secret**.\n - Provide a description, set an expiry, and click **Add**.\n - Copy the **Value** of the client secret (this will not be shown again).\n11. Go to **API permissions** from the left menu.\n - Click **Add a permission**.\n - Select **Dynamics CRM** → **Delegated permissions**.\n - Click **Add permissions**.\n12. Copy your **Client ID** and **Client Secret**.\n",
"Create Record": "Create Record",
"Delete Record": "Delete Record",
"Get Record": "Get Record",
"Update Record": "Update Record",
"Custom API Call": "自定义 API 呼叫",
"Creates a new record.": "Creates a new record.",
"Deletes an existing record.": "Deletes an existing record.",
"Retrieves an existing record.": "Retrieves an existing record.",
"Updates an existing record.": "Updates an existing record.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Entity Type": "Entity Type",
"Entity Fields": "Entity Fields",
"Record ID": "Record ID",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Select or map the entity for which you want to create the record.": "Select or map the entity for which you want to create the record.",
"Select or map the entity name whose records you want to delete.": "Select or map the entity name whose records you want to delete.",
"Select or map the entity name whose records you want to retrieve.": "Select or map the entity name whose records you want to retrieve.",
"Select or map the entity for which you want to update the record.": "Select or map the entity for which you want to update the record.",
"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": "黑色"
}

View File

@@ -0,0 +1,105 @@
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import {
createPiece,
OAuth2PropertyValue,
PieceAuth,
Property,
} from '@activepieces/pieces-framework';
import { createRecordAction } from './lib/actions/create-record';
import { deleteRecordAction } from './lib/actions/delete-record';
import { getRecordAction } from './lib/actions/get-record';
import { updateRecordAction } from './lib/actions/update-record';
import { PieceCategory } from '@activepieces/shared';
const authDesc = `
1. Sign in to [Microsoft Azure Portal](https://portal.azure.com/).
2. From the left sidebar, go to **Microsoft Enfra ID**.
3. Under **Manage**, click on **App registrations**.
4. Click the **New registration** button.
5. Enter a **Name** for your app.
6. For **Supported account types**, choose:
- **Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts**
- Or select based on your requirement.
7. In **Redirect URI**, select **Web** and add the given URL.
8. Click **Register**.
9. After registration, youll be redirected to the apps overview page. Copy the **Application (client) ID**.
10. From the left menu, go to **Certificates & secrets**.
- Under **Client secrets**, click **New client secret**.
- Provide a description, set an expiry, and click **Add**.
- Copy the **Value** of the client secret (this will not be shown again).
11. Go to **API permissions** from the left menu.
- Click **Add a permission**.
- Select **Dynamics CRM** → **Delegated permissions**.
- Click **Add permissions**.
12. Copy your **Client ID** and **Client Secret**.
`
export const dynamicsCRMAuth = PieceAuth.OAuth2({
description:authDesc,
props: {
hostUrl: Property.ShortText({
displayName: 'Host URL (without trailing slash)',
description:
'Host URL without trailing slash.For example **https://demo.crm.dynamics.com**',
required: true,
}),
tenantId: Property.ShortText({
displayName: 'Tenant ID',
description: 'You can find this in the Azure portal.',
defaultValue: 'common',
required: true,
}),
proxyUrl: Property.ShortText({
displayName: 'Proxy URL with Port',
description:
'Keep empty if not needed. Optional proxy URL used for establishing connections when proxying requests is needed. For example: **https://proxy.com:8080**.',
required: false,
}),
},
required: true,
scope: ['{hostUrl}/.default', 'openid', 'email', 'profile', 'offline_access'],
prompt: 'omit',
authUrl: 'https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize',
tokenUrl: 'https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token',
});
export function getBaseUrl(host: string, proxyUrl?: string): string {
if (proxyUrl && proxyUrl !== '') {
return proxyUrl;
}
return host;
}
export const microsoftDynamicsCrm = createPiece({
displayName: 'Microsoft Dynamics CRM',
auth: dynamicsCRMAuth,
description:
'Customer relationship management software package developed by Microsoft.',
minimumSupportedRelease: '0.27.1',
logoUrl: 'https://cdn.activepieces.com/pieces/microsoft-dynamics-crm.png',
authors: ['kishanprmr'],
categories: [PieceCategory.SALES_AND_CRM],
actions: [
createRecordAction,
deleteRecordAction,
getRecordAction,
updateRecordAction,
createCustomApiCallAction({
auth: dynamicsCRMAuth,
baseUrl: (auth) => {
const props = auth?.props
if (!props) {
return '';
}
return `${getBaseUrl(
props['hostUrl'] as string,
props['proxyUrl'] as string
)}/api/data/v9.2`;
},
authMapping: async (auth) => ({
Authorization: `Bearer ${(auth ).access_token}`,
}),
}),
],
triggers: [],
});

View File

@@ -0,0 +1,30 @@
import {
PiecePropValueSchema,
createAction,
} from '@activepieces/pieces-framework';
import { dynamicsCRMAuth } from '../../';
import { DynamicsCRMCommon, makeClient } from '../common';
export const createRecordAction = createAction({
auth: dynamicsCRMAuth,
name: 'dynamics_crm_create_record',
displayName: 'Create Record',
description: 'Creates a new record.',
props: {
entityType: DynamicsCRMCommon.entityType(
'Select or map the entity for which you want to create the record.'
),
fields: DynamicsCRMCommon.entityFields(true),
},
async run(context) {
const { entityType, fields } = context.propsValue;
const entityUrlPath = entityType as string;
const client = makeClient(
context.auth
);
return await client.createRecord(entityUrlPath, fields);
},
});

View File

@@ -0,0 +1,30 @@
import {
PiecePropValueSchema,
createAction,
} from '@activepieces/pieces-framework';
import { dynamicsCRMAuth } from '../../';
import { DynamicsCRMCommon, makeClient } from '../common';
export const deleteRecordAction = createAction({
auth: dynamicsCRMAuth,
name: 'dynamics_crm_delete_record',
displayName: 'Delete Record',
description: 'Deletes an existing record.',
props: {
entityType: DynamicsCRMCommon.entityType(
'Select or map the entity name whose records you want to delete.'
),
recordId: DynamicsCRMCommon.recordId,
},
async run(context) {
const { entityType, recordId } = context.propsValue;
const entityUrlPath = entityType as string;
const client = makeClient(
context.auth
);
return await client.deleteRecord(entityUrlPath, recordId);
},
});

View File

@@ -0,0 +1,30 @@
import {
PiecePropValueSchema,
createAction,
} from '@activepieces/pieces-framework';
import { dynamicsCRMAuth } from '../../';
import { DynamicsCRMCommon, makeClient } from '../common';
export const getRecordAction = createAction({
auth: dynamicsCRMAuth,
name: 'dynamics_crm_get_record',
displayName: 'Get Record',
description: 'Retrieves an existing record.',
props: {
entityType: DynamicsCRMCommon.entityType(
'Select or map the entity name whose records you want to retrieve.'
),
recordId: DynamicsCRMCommon.recordId,
},
async run(context) {
const { entityType, recordId } = context.propsValue;
const entityUrlPath = entityType as string;
const client = makeClient(
context.auth
);
return await client.getRecord(entityUrlPath, recordId);
},
});

View File

@@ -0,0 +1,31 @@
import {
PiecePropValueSchema,
createAction,
} from '@activepieces/pieces-framework';
import { dynamicsCRMAuth } from '../../';
import { DynamicsCRMCommon, makeClient } from '../common';
export const updateRecordAction = createAction({
auth: dynamicsCRMAuth,
name: 'dynamics_crm_update_record',
displayName: 'Update Record',
description: 'Updates an existing record.',
props: {
entityType: DynamicsCRMCommon.entityType(
'Select or map the entity for which you want to update the record.'
),
recordId: DynamicsCRMCommon.recordId,
fields: DynamicsCRMCommon.entityFields(false),
},
async run(context) {
const { entityType, recordId, fields } = context.propsValue;
const entityUrlPath = entityType as string;
const client = makeClient(
context.auth
);
return await client.updatedRecord(entityUrlPath, recordId, fields);
},
});

View File

@@ -0,0 +1,169 @@
import {
AuthenticationType,
HttpHeaders,
HttpMessageBody,
HttpMethod,
QueryParams,
httpClient,
} from '@activepieces/pieces-common';
import { EntityAttributeType } from './constants';
import {
EntityAttributeOptionsResponse,
EntityAttributeResponse,
EntityTypeAttributesResponse,
EntityTypeResponse,
} from './types';
import { getBaseUrl } from '../..';
export class DynamicsCRMClient {
constructor(
private hostUrl: string,
private accessToken: string,
private proxyUrl?: string
) {}
async makeRequest<T extends HttpMessageBody>(
method: HttpMethod,
resourceUri: string,
headers?: HttpHeaders,
query?: QueryParams,
body: any | undefined = undefined
): Promise<T> {
const baseUrl = getBaseUrl(this.hostUrl.replace(/\/$/, ''), this.proxyUrl);
const res = await httpClient.sendRequest<T>({
method: method,
url: `${baseUrl}/api/data/v9.2` + resourceUri,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: this.accessToken,
},
headers: {
Accept: 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
'Content-Type': 'application/json',
...headers,
},
queryParams: query,
body: body,
});
return res.body;
}
async createRecord(entityUrlPath: string, request: unknown) {
return await this.makeRequest(
HttpMethod.POST,
`/${entityUrlPath}`,
{
// return created data in response
// docs: https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg328090(v=crm.8)#create-with-data-returned
Prefer: 'return=representation',
},
undefined,
request
);
}
async updatedRecord(
entityUrlPath: string,
recordId: string,
request: unknown
) {
return await this.makeRequest(
HttpMethod.PATCH,
`/${entityUrlPath}(${recordId})`,
{
// return created data in response
// docs: https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/mt607664(v=crm.8)#update-with-data-returned
Prefer: 'return=representation',
},
undefined,
request
);
}
async getRecord(entityUrlPath: string, recordId: string) {
return await this.makeRequest(
HttpMethod.GET,
`/${entityUrlPath}(${recordId})`
);
}
async deleteRecord(entityUrlPath: string, recordId: string) {
return await this.makeRequest(
HttpMethod.DELETE,
`/${entityUrlPath}(${recordId})`
);
}
async fetchEntityTypes(): Promise<EntityTypeResponse> {
// fetch entity type data
return await this.makeRequest<EntityTypeResponse>(
HttpMethod.GET,
`/EntityDefinitions`,
undefined,
{
$select: ['EntitySetName', 'LogicalName'].join(','),
}
);
}
async fetchEntityTypeAttributes(
entitySetName: string
): Promise<EntityTypeAttributesResponse> {
return await this.makeRequest<EntityTypeAttributesResponse>(
HttpMethod.GET,
`/EntityDefinitions`,
undefined,
{
$select: [
'PrimaryIdAttribute',
'PrimaryNameAttribute',
'LogicalName',
].join(','),
$filter: `EntitySetName eq '${entitySetName}'`,
}
);
}
async fetchEntityAttributes(
entityName: string
): Promise<EntityAttributeResponse> {
// fetch entity attribute data
// docs: https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/mt788314(v=crm.8)#retrieve-metadata-items-by-name
return await this.makeRequest<EntityAttributeResponse>(
HttpMethod.GET,
`/EntityDefinitions(LogicalName='${entityName}')/Attributes`,
undefined,
{
$select: [
'AttributeType',
'LogicalName',
'Description',
'DisplayName',
'IsPrimaryName',
'IsValidForCreate',
].join(','),
}
);
}
async fetchOptionFieldValues(
entityName: string,
entityAttributeName: string,
entityAttributeType: EntityAttributeType
): Promise<{ label: string; value: string | number }[]> {
const res = await this.makeRequest<EntityAttributeOptionsResponse>(
HttpMethod.GET,
`/EntityDefinitions(LogicalName='${entityName}')/Attributes(LogicalName='${entityAttributeName}')/Microsoft.Dynamics.CRM.${entityAttributeType}AttributeMetadata`,
undefined,
{
$select: 'LogicalName',
$expand: 'OptionSet($select=Options),GlobalOptionSet($select=Options)',
}
);
const optionSet = res.OptionSet ?? res.GlobalOptionSet;
const options: { label: string; value: string | number }[] =
optionSet?.Options?.map(({ Value, Label }) => ({
value: Value,
label: Label.UserLocalizedLabel.Label ?? String(Value),
})) || [];
return options;
}
}

View File

@@ -0,0 +1,21 @@
// docs: https://learn.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/mt608066(v=crm.8)
export enum EntityAttributeType {
PICKLIST = 'Picklist',
VIRTUAL = 'Virtual',
UNIQUE_IDENTIFIER = 'Uniqueidentifier',
STRING = 'String',
MEMO = 'Memo',
MONEY = 'Money',
DOUBLE = 'Double',
INTEGER = 'Integer',
LOOKUP = 'Lookup',
DATETIME = 'DateTime',
BOOLEAN = 'Boolean',
BIGINT = 'BigInt',
DECIMAL = 'Decimal',
OWNER = 'Owner',
ENTITY_NAME = 'EntityName',
STATE = 'State',
STATUS = 'Status',
}

View File

@@ -0,0 +1,229 @@
import {
AuthenticationType,
HttpMethod,
HttpRequest,
httpClient,
} from '@activepieces/pieces-common';
import {
DynamicPropsValue,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
import { dynamicsCRMAuth, getBaseUrl } from '../../';
import { DynamicsCRMClient } from './client';
import { EntityAttributeType } from './constants';
export function makeClient(auth: PiecePropValueSchema<typeof dynamicsCRMAuth>) {
const client = new DynamicsCRMClient(
auth.props?.['hostUrl'],
auth.access_token,
auth.props?.['proxyUrl']
);
return client;
}
export const DynamicsCRMCommon = {
entityType: (description: string) =>
Property.Dropdown({
auth: dynamicsCRMAuth,
displayName: 'Entity Type',
refreshers: [],
description,
required: true,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
options: [],
placeholder: '',
};
}
const client = makeClient(
auth
);
const res = await client.fetchEntityTypes();
return {
disabled: false,
options: res.value.map((val) => {
return {
label: val.EntitySetName,
value: val.EntitySetName,
};
}),
};
},
}),
recordId: Property.Dropdown({
auth: dynamicsCRMAuth,
displayName: 'Record ID',
refreshers: ['entityType'],
required: true,
options: async ({ auth, entityType }) => {
if (!auth || !entityType) {
return {
disabled: true,
options: [],
placeholder: 'Please select entity type first.',
};
}
const client = makeClient(
auth as PiecePropValueSchema<typeof dynamicsCRMAuth>
);
const res = await client.fetchEntityTypeAttributes(entityType as string);
if (!res.value[0]) {
return {
disabled: true,
options: [],
placeholder: 'Please select entity type first.',
};
}
const entityUrlPath = entityType as string;
const entityPrimaryKey = res.value[0].PrimaryIdAttribute;
const entityprimaryNameAttribute = res.value[0].PrimaryNameAttribute;
const authValue = auth as PiecePropValueSchema<typeof dynamicsCRMAuth>;
type Response = {
'@odata.context': string;
value: Array<{
[K in
| typeof entityprimaryNameAttribute
| typeof entityPrimaryKey]: string;
}>;
};
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${getBaseUrl(
authValue.props?.['hostUrl'],
authValue.props?.['proxyUrl']
)}/api/data/v9.2/${entityUrlPath}`,
queryParams: {
$select: entityprimaryNameAttribute,
},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authValue.access_token,
},
headers: {
Accept: 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
'Content-Type': 'application/json',
},
};
const { body } = await httpClient.sendRequest<Response>(request);
return {
disabled: false,
options: body.value.map((val) => {
return {
label: val[entityprimaryNameAttribute] ?? val[entityPrimaryKey],
value: val[entityPrimaryKey],
};
}),
};
},
}),
entityFields: (isCreate = true) =>
Property.DynamicProperties({
auth: dynamicsCRMAuth,
displayName: 'Entity Fields',
refreshers: ['auth', 'entityType'],
required: true,
props: async ({ auth, entityType }) => {
if (!auth) return {};
if (!entityType) return {};
const fields: DynamicPropsValue = {};
const client = makeClient(
auth
);
const typeRes = await client.fetchEntityTypeAttributes(
entityType as unknown as string
);
if (!typeRes.value[0]) {
return {
disabled: true,
options: [],
placeholder: 'Please select entity type first.',
};
}
const res = await client.fetchEntityAttributes(
typeRes.value[0].LogicalName
);
for (const field of res.value) {
if (
field.IsValidForCreate &&
![
EntityAttributeType.ENTITY_NAME,
EntityAttributeType.LOOKUP,
EntityAttributeType.MEMO,
EntityAttributeType.MONEY,
EntityAttributeType.OWNER,
EntityAttributeType.VIRTUAL,
EntityAttributeType.UNIQUE_IDENTIFIER,
].includes(field.AttributeType)
) {
const params = {
displayName:
field.DisplayName?.UserLocalizedLabel?.Label ??
field.LogicalName,
description: field.Description?.UserLocalizedLabel?.Label ?? '',
required: field.IsPrimaryName && isCreate,
};
switch (field.AttributeType) {
case EntityAttributeType.BIGINT:
case EntityAttributeType.DECIMAL:
case EntityAttributeType.DOUBLE:
case EntityAttributeType.INTEGER:
fields[field.LogicalName] = Property.Number(params);
break;
case EntityAttributeType.DATETIME:
fields[field.LogicalName] = Property.DateTime(params);
break;
case EntityAttributeType.BOOLEAN:
fields[field.LogicalName] = Property.Checkbox(params);
break;
case EntityAttributeType.STRING:
fields[field.LogicalName] = Property.ShortText(params);
break;
case EntityAttributeType.PICKLIST:
case EntityAttributeType.STATE:
case EntityAttributeType.STATUS: {
const options = await client.fetchOptionFieldValues(
typeRes.value[0].LogicalName,
field.LogicalName,
field.AttributeType
);
fields[field.LogicalName] = Property.StaticDropdown({
...params,
options: {
disabled: false,
options: options,
},
});
break;
}
default:
break;
}
}
}
return fields;
},
}),
};

View File

@@ -0,0 +1,85 @@
import { EntityAttributeType } from './constants';
export type EntityTypeResponse = {
'@odata.context': string;
value: {
'@odata.type': string;
LogicalName: string;
EntitySetName: string;
}[];
};
export type EntityTypeAttributesResponse = {
'@odata.context': string;
value: {
'@odata.type': string;
PrimaryIdAttribute: string;
PrimaryNameAttribute: string;
LogicalName: string;
}[];
};
export type EntityAttributeResponse = {
'@odata.context': string;
value: {
'@odata.type': string;
AttributeType: EntityAttributeType;
LogicalName: string;
MetadataId: string;
IsValidForCreate: boolean;
IsPrimaryName: boolean;
Description: {
UserLocalizedLabel: {
Label: string;
LanguageCode: number;
IsManaged: boolean;
MetadataId: string;
HasChanged: boolean;
} | null;
} | null;
DisplayName: {
UserLocalizedLabel: {
Label: string;
LanguageCode: number;
IsManaged: boolean;
MetadataId: string;
HasChanged: boolean;
} | null;
} | null;
}[];
};
export type EntityAttributeOptionsResponse = {
'@odata.context': string;
LogicalName: string;
MetadataId: string;
OptionSet: {
MetadataId: string;
Options: {
Value: number;
Label: {
UserLocalizedLabel: {
Label: string;
LanguageCode: number;
IsManaged: boolean;
MetadataId: string;
HasChanged: boolean;
};
};
}[];
} | null;
GlobalOptionSet: {
MetadataId: string;
Options: {
Value: number;
Label: {
UserLocalizedLabel: {
Label: string;
LanguageCode: number;
IsManaged: boolean;
MetadataId: string;
HasChanged: boolean;
};
};
}[];
} | null;
};

View File

@@ -0,0 +1,19 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}