Add n8n Integration to Formbricks (#733)
* add n8n integration * add n8n inside packages * added documentation for n8n setup * add formbricks scope to package * add changeset config for automatic package deployment * remove old docs navigation * add new package README * update prettier config & reformat --------- Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
5
.changeset/slimy-rats-flash.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@formbricks/n8n-nodes-formbricks": minor
|
||||
---
|
||||
|
||||
Add new n8n Integration for Formbricks; huge thanks to @PratikAwaik
|
||||
@@ -48,7 +48,7 @@ Formbricks helps you apply best practices from data-driven work and experience m
|
||||
- 👩🏻 Launch and **target your surveys to specific user groups** without changing your application code
|
||||
- 🔗 Create shareable **link surveys**
|
||||
- 👨👩👦 Invite your team members to **collaborate** on your surveys
|
||||
- 🔌 Integrate Formbricks with **Slack, Posthog, Zapier and more**
|
||||
- 🔌 Integrate Formbricks with **Slack, Posthog, Zapier, n8n and more**
|
||||
- 🔒 All **open source**, transparent and self-hostable
|
||||
|
||||
### Built on Open Source
|
||||
|
||||
BIN
apps/formbricks-com/app/docs/integrations/n8n/add-api-key.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
apps/formbricks-com/app/docs/integrations/n8n/add-discord.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 460 KiB |
|
After Width: | Height: | Size: 46 KiB |
126
apps/formbricks-com/app/docs/integrations/n8n/page.mdx
Normal file
@@ -0,0 +1,126 @@
|
||||
import { Fence } from "@/components/shared/Fence";
|
||||
import { Callout } from "@/components/shared/Callout";
|
||||
import Image from "next/image";
|
||||
|
||||
import AddFormbricksTrigger from "./add-formbricks-trigger.png";
|
||||
import CreateNewCredentialBtn from "./create-new-credential-btn.png";
|
||||
import AddApiKey from "./add-api-key.png";
|
||||
import DuplicateSurvey from "./duplicate-survey.png";
|
||||
import SelectEvent from "./select-event.png";
|
||||
import SelectSurvey from "./select-survey.png";
|
||||
import SelectedSurveys from "./selected-surveys.png";
|
||||
import ListenForEvent from "./listen-for-event.png";
|
||||
import TestResponseSuccess from "./test-response-success.png";
|
||||
import AddDiscord from "./add-discord.png";
|
||||
import FillDiscordDetails from "./fill-discord-details.png";
|
||||
import DiscordResponse from "./discord-response.png";
|
||||
import SubmitTestResponse from "./submit-test-response.png";
|
||||
import SuccessConnection from "./success-connection.png";
|
||||
import UpdateQuestionId from "./update-question-id.png";
|
||||
|
||||
export const meta = {
|
||||
title: "n8n Setup",
|
||||
description: "Wire up Formbricks with n8n and 350+ other apps",
|
||||
};
|
||||
|
||||
#### Integrations
|
||||
|
||||
# n8n Setup
|
||||
|
||||
n8n allows you to build flexible workflows focused on deep data integration. And with sharable templates and a user-friendly UI, the less technical people on your team can collaborate on them too. Unlike other tools, complexity is not a limitation. So you can build whatever you want — without stressing over budget. Hook up Formbricks with n8n and you can send your data to 350+ other apps. Here is how to do it.
|
||||
|
||||
<Note>
|
||||
### Nail down your survey first {{ class: "text-white" }}
|
||||
Any changes in the survey cause additional work in the n8n node. It makes sense to first settle on the survey
|
||||
you want to run and then get to setting up n8n.
|
||||
</Note>
|
||||
|
||||
## Step 1: Setup your survey incl. `questionId` for every question
|
||||
|
||||
When setting up the node your life will be easier when you change the `questionId`s of your survey questions. You can only do so **before** you publish your survey.
|
||||
|
||||
<Image src={UpdateQuestionId} alt="Update Question ID" quality="100" className="rounded-lg" />
|
||||
|
||||
_In every question card in the Advanced Settings you find the Question ID field. Update it so that you'll recognize the response tied to this question._
|
||||
|
||||
<Note>
|
||||
### Already published? Duplicate survey {{ class: "text-white" }}
|
||||
You can only update the questionId when the survey was not yet published. Already published it? Just **duplicate
|
||||
it** to update the questionIds.
|
||||
<Image
|
||||
src={DuplicateSurvey}
|
||||
alt="Duplicate Survey"
|
||||
quality="100"
|
||||
className="rounded-lg max-w-full sm:max-w-3xl"
|
||||
/>
|
||||
</Note>
|
||||
|
||||
## Step 2: Setup your n8n workflow
|
||||
|
||||
Go to [n8n.io](https://n8n.io) and create a new workflow. Search for “Formbricks” to get started:
|
||||
|
||||
<Image src={AddFormbricksTrigger} alt="Add Formbricks Trigger" quality="100" className="rounded-lg" />
|
||||
|
||||
## Step 3: Connect Formbricks with n8n
|
||||
|
||||
Now, you have to connect n8n with Formbricks via an API Key:
|
||||
|
||||
<Image src={CreateNewCredentialBtn} alt="Create new credential button" quality="100" className="rounded-lg" />
|
||||
|
||||
Click on Create New Credentail button to add your host and API Key
|
||||
|
||||
<Image src={AddApiKey} alt="Add host and api key" quality="100" className="rounded-lg" />
|
||||
|
||||
Now you need an API key. Please refer to the [API Key Setup](/docs/api/api-key-setup) page to learn how to create one.
|
||||
|
||||
Once you copied it in the API Key field, hit Save button to test the connection and save the credentials.
|
||||
|
||||
<Image src={SuccessConnection} alt="Successful Connection" quality="100" className="rounded-lg" />
|
||||
|
||||
## Step 4: Select Event
|
||||
|
||||
Next, you can choose the event you want to trigger the node on. You can select multiple events:
|
||||
|
||||
<Image src={SelectEvent} alt="Select Event" quality="100" className="rounded-lg" />
|
||||
|
||||
Here, we are adding `Response Finished` as an event, which will trigger when the survey has been filled out.
|
||||
|
||||
## Step 5: Select Survey
|
||||
|
||||
Next, you can choose from all the surveys you have created in this environment. You can select multiple surveys:
|
||||
|
||||
<Image src={SelectSurvey} alt="Select Survey" quality="100" className="rounded-lg" />
|
||||
|
||||
Here, we are selecting two surveys.
|
||||
|
||||
<Image src={SelectedSurveys} alt="Selected Surveys" quality="100" className="rounded-lg" />
|
||||
|
||||
## Step 6: Test your trigger
|
||||
|
||||
In order to set up n8n you'll need a test response in the selected survey. This allows you to select the individual values of each response in your workflow. If you have Formbricks running locally and you want to set up an in-app survey, you can use our [Demo App](/docs/contributing/demo) to trigger a survey and submit a response.
|
||||
|
||||
<Image src={SubmitTestResponse} alt="Submit Test Response" quality="100" className="rounded-lg" />
|
||||
|
||||
Next, click on Listen for event button.
|
||||
|
||||
<Image src={ListenForEvent} alt="Listen for event" quality="100" className="rounded-lg" />
|
||||
|
||||
Then, go to the survey which you selected. Fill it out, and wait for the particular event to trigger (in this case it's `Response Finished`). Once the event is triggered you will see the response that you filled out in the survey.
|
||||
|
||||
<Image src={TestResponseSuccess} alt="Test Response Success" quality="100" className="rounded-lg" />
|
||||
|
||||
Now you have all the data you need at hand. The next steps depend on what you want to do with it. In this tutorial, we will send submissions to a discord channel:
|
||||
|
||||
## Step 7: Add discord to your workflow
|
||||
|
||||
Click on the plus and search `Discord`.
|
||||
|
||||
<Image src={AddDiscord} alt="Add Discord" quality="100" className="rounded-lg" />
|
||||
|
||||
Fill in the `Webhook URL` and the `Content` that you want to receive in the respective discord channel. Next, click on `Execute Node` button to test the node.
|
||||
|
||||
<Image src={FillDiscordDetails} alt="Fill Discord Details" quality="100" className="rounded-lg" />
|
||||
|
||||
Once the execution is successful, you'll receive the content in the discord channel.
|
||||
|
||||
<Image src={DiscordResponse} alt="Discord Response" quality="100" className="rounded-lg" />
|
||||
BIN
apps/formbricks-com/app/docs/integrations/n8n/select-event.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
apps/formbricks-com/app/docs/integrations/n8n/select-survey.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -225,7 +225,10 @@ export const navigation: Array<NavGroup> = [
|
||||
},
|
||||
{
|
||||
title: "Integrations",
|
||||
links: [{ title: "Zapier", href: "/docs/integrations/zapier" }],
|
||||
links: [
|
||||
{ title: "Zapier", href: "/docs/integrations/zapier" },
|
||||
{ title: "n8n", href: "/docs/integrations/n8n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Link Surveys",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import JsLogo from "@/images/jslogo.png";
|
||||
import WebhookLogo from "@/images/webhook.png";
|
||||
import ZapierLogo from "@/images/zapier-small.png";
|
||||
import n8nLogo from "@/images/n8n.png";
|
||||
import { Card } from "@formbricks/ui";
|
||||
import Image from "next/image";
|
||||
|
||||
@@ -40,6 +41,17 @@ export default function IntegrationsPage({ params }) {
|
||||
description="Trigger Webhooks based on actions in your surveys"
|
||||
icon={<Image src={WebhookLogo} alt="Webhook Logo" />}
|
||||
/>
|
||||
<Card
|
||||
docsHref="https://formbricks.com/docs/integrations/n8n"
|
||||
docsText="Docs"
|
||||
docsNewTab={true}
|
||||
connectHref="https://n8n.io"
|
||||
connectText="Connect"
|
||||
connectNewTab={true}
|
||||
label="n8n"
|
||||
description="Integrate Formbricks with 350+ apps via n8n"
|
||||
icon={<Image src={n8nLogo} alt="n8n Logo" />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
BIN
apps/web/images/n8n.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
20
packages/n8n/.editorconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[package.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
53
packages/n8n/.eslintrc.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
|
||||
parser: "@typescript-eslint/parser",
|
||||
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.json"],
|
||||
sourceType: "module",
|
||||
extraFileExtensions: [".json"],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
|
||||
ignorePatterns: [".eslintrc.js", "**/*.js", "**/node_modules/**", "**/dist/**"],
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: ["package.json"],
|
||||
plugins: ["eslint-plugin-n8n-nodes-base"],
|
||||
extends: ["plugin:n8n-nodes-base/community"],
|
||||
rules: {
|
||||
"n8n-nodes-base/community-package-json-name-still-default": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["./credentials/**/*.ts"],
|
||||
plugins: ["eslint-plugin-n8n-nodes-base"],
|
||||
extends: ["plugin:n8n-nodes-base/credentials"],
|
||||
rules: {
|
||||
"n8n-nodes-base/cred-class-field-documentation-url-missing": "off",
|
||||
"n8n-nodes-base/cred-class-field-documentation-url-miscased": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["./nodes/**/*.ts"],
|
||||
plugins: ["eslint-plugin-n8n-nodes-base"],
|
||||
extends: ["plugin:n8n-nodes-base/nodes"],
|
||||
rules: {
|
||||
"n8n-nodes-base/node-execute-block-missing-continue-on-fail": "off",
|
||||
"n8n-nodes-base/node-resource-description-filename-against-convention": "off",
|
||||
"n8n-nodes-base/node-param-fixed-collection-type-unsorted-items": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
16
packages/n8n/.eslintrc.prepublish.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @type {import('@types/eslint').ESLint.ConfigData}
|
||||
*/
|
||||
module.exports = {
|
||||
extends: "./.eslintrc.js",
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: ['package.json'],
|
||||
plugins: ['eslint-plugin-n8n-nodes-base'],
|
||||
rules: {
|
||||
'n8n-nodes-base/community-package-json-name-still-default': 'error',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
8
packages/n8n/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
.tmp
|
||||
tmp
|
||||
dist
|
||||
npm-debug.log*
|
||||
yarn.lock
|
||||
.vscode/launch.json
|
||||
2
packages/n8n/.npmignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
*.tsbuildinfo
|
||||
7
packages/n8n/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode",
|
||||
]
|
||||
}
|
||||
19
packages/n8n/LICENSE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright 2022 n8n
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
39
packages/n8n/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# n8n-nodes-formbricks
|
||||
|
||||
This is an n8n community node. It lets you use Formbricks in your n8n workflows.
|
||||
|
||||
Formbricks is an open-source experience management solution that lets you understand what customers think & feel about your product by running highly targeted surveys inside your product.
|
||||
|
||||
[n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
|
||||
|
||||
[Installation](#installation)
|
||||
[Operations](#operations)
|
||||
[Credentials](#credentials) <!-- delete if no auth needed -->
|
||||
[Compatibility](#compatibility)
|
||||
[Usage](#usage) <!-- delete if not using this section -->
|
||||
[Resources](#resources)
|
||||
|
||||
## Installation
|
||||
|
||||
Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
|
||||
|
||||
## Operations
|
||||
|
||||
Run workflows on new responses you receive for your surveys.
|
||||
|
||||
## Credentials
|
||||
|
||||
You can use this integration in Formbricks Cloud as well as self-hosted instances of Formbricks. You only need a Formbricks API Key for this. Please check out the [Formbricks Docs]() for more information.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This package was developed & tested with n8n > 1.4.0.
|
||||
|
||||
## Usage
|
||||
|
||||
Please check out the [Formbricks Docs](https://formbricks.com/docs/api/api-key-setup) for more information on how to use the integration.
|
||||
|
||||
## Resources
|
||||
|
||||
- [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
|
||||
- [Formbricks Docs](https://formbricks.com/docs/integrations/n8n)
|
||||
40
packages/n8n/credentials/FormbricksApi.credentials.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from "n8n-workflow";
|
||||
|
||||
export class FormbricksApi implements ICredentialType {
|
||||
name = "formbricksApi";
|
||||
displayName = "Formbricks API";
|
||||
properties: INodeProperties[] = [
|
||||
{
|
||||
displayName: "Host",
|
||||
name: "host",
|
||||
description:
|
||||
'The address of your Formbricks instance. For Formbricks Cloud this is "https://app.formbricks.com". If you are hosting Formbricks yourself, it\'s the address where you can reach your instance.',
|
||||
type: "string",
|
||||
default: "https://app.formbricks.com",
|
||||
},
|
||||
{
|
||||
displayName: "API Key",
|
||||
name: "apiKey",
|
||||
description:
|
||||
'Your Formbricks API-Key. You can create a new API-Key in the Product Settings. Please read our <a href="https://formbricks.com/docs/api/api-key-setup">API Key Docs</a> for more details.',
|
||||
type: "string",
|
||||
typeOptions: { password: true },
|
||||
default: "",
|
||||
},
|
||||
];
|
||||
|
||||
authenticate: IAuthenticateGeneric = {
|
||||
type: "generic",
|
||||
properties: {
|
||||
headers: {
|
||||
"x-Api-Key": "={{$credentials.apiKey}}",
|
||||
},
|
||||
},
|
||||
};
|
||||
test: ICredentialTestRequest | undefined = {
|
||||
request: {
|
||||
baseURL: "={{$credentials.host}}/api/v1",
|
||||
url: "=/me",
|
||||
},
|
||||
};
|
||||
}
|
||||
16
packages/n8n/gulpfile.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const { task, src, dest } = require('gulp');
|
||||
|
||||
task('build:icons', copyIcons);
|
||||
|
||||
function copyIcons() {
|
||||
const nodeSource = path.resolve('nodes', '**', '*.{png,svg}');
|
||||
const nodeDestination = path.resolve('dist', 'nodes');
|
||||
|
||||
src(nodeSource).pipe(dest(nodeDestination));
|
||||
|
||||
const credSource = path.resolve('credentials', '**', '*.{png,svg}');
|
||||
const credDestination = path.resolve('dist', 'credentials');
|
||||
|
||||
return src(credSource).pipe(dest(credDestination));
|
||||
}
|
||||
0
packages/n8n/index.js
Normal file
18
packages/n8n/nodes/Formbricks/Formbricks.node.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.Formbricks",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Communication"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/credentials/formbricks"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.formbricks/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
155
packages/n8n/nodes/Formbricks/Formbricks.node.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import { INodeType, INodeTypeDescription, IWebhookFunctions, IWebhookResponseData } from "n8n-workflow";
|
||||
|
||||
import { apiRequest, getSurveys } from "./GenericFunctions";
|
||||
import { IHookFunctions } from "n8n-core";
|
||||
|
||||
export class Formbricks implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: "Formbricks",
|
||||
name: "formbricks",
|
||||
icon: "file:formbricks.svg",
|
||||
group: ["trigger"],
|
||||
version: 1,
|
||||
subtitle: '=Surveys: {{$parameter["surveyIds"]}}',
|
||||
description: "Open Source Surveys & Experience Management Solution",
|
||||
defaults: {
|
||||
name: "Formbricks",
|
||||
},
|
||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
||||
inputs: [],
|
||||
outputs: ["main"],
|
||||
credentials: [
|
||||
{
|
||||
name: "formbricksApi",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
name: "default",
|
||||
httpMethod: "POST",
|
||||
responseMode: "onReceived",
|
||||
path: "webhook",
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: "Events",
|
||||
name: "events",
|
||||
type: "multiOptions",
|
||||
options: [
|
||||
{
|
||||
name: "Response Created",
|
||||
value: "responseCreated",
|
||||
description:
|
||||
"Triggers when a new response is created for a survey. Normally triggered after the first question was answered.",
|
||||
},
|
||||
{
|
||||
name: "Response Updated",
|
||||
value: "responseUpdated",
|
||||
description: "Triggers when a response is updated within a survey",
|
||||
},
|
||||
{
|
||||
name: "Response Finished",
|
||||
value: "responseFinished",
|
||||
description: "Triggers when a response is marked as finished",
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-multi-options
|
||||
displayName: "Survey",
|
||||
name: "surveyIds",
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-description-wrong-for-dynamic-multi-options
|
||||
description:
|
||||
'Survey which should trigger workflow. Only trigger this node for a specific survey within the environment. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
||||
type: "multiOptions",
|
||||
typeOptions: {
|
||||
loadOptionsMethod: "getSurveys",
|
||||
},
|
||||
options: [],
|
||||
default: [],
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
methods = {
|
||||
loadOptions: {
|
||||
getSurveys,
|
||||
},
|
||||
};
|
||||
|
||||
webhookMethods = {
|
||||
default: {
|
||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData("node");
|
||||
const webhookUrl = this.getNodeWebhookUrl("default");
|
||||
const surveyIds = this.getNodeParameter("surveyIds") as Array<string>;
|
||||
|
||||
const endpoint = "/webhooks";
|
||||
|
||||
try {
|
||||
const response = await apiRequest.call(this, "GET", endpoint, {});
|
||||
for (const webhook of response.data) {
|
||||
for (const surveyId of webhook.surveyIds) {
|
||||
if (surveyIds.includes(surveyId) && webhook.url === webhookUrl) {
|
||||
webhookData.webhookId = webhook.id;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
async create(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData("node");
|
||||
const webhookUrl = this.getNodeWebhookUrl("default");
|
||||
const surveyIds = this.getNodeParameter("surveyIds") as Array<string>;
|
||||
const events = this.getNodeParameter("events");
|
||||
|
||||
const body = {
|
||||
url: webhookUrl,
|
||||
triggers: events,
|
||||
surveyIds: surveyIds,
|
||||
};
|
||||
const endpoint = "/webhooks";
|
||||
|
||||
try {
|
||||
const response = await apiRequest.call(this, "POST", endpoint, body);
|
||||
webhookData.webhookId = response.data.id;
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async delete(this: IHookFunctions): Promise<boolean> {
|
||||
const webhookData = this.getWorkflowStaticData("node");
|
||||
if (webhookData.webhookId !== undefined) {
|
||||
const endpoint = `/webhooks/${webhookData.webhookId}`;
|
||||
|
||||
try {
|
||||
await apiRequest.call(this, "DELETE", endpoint, {});
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
// Remove from the static workflow data so that it is clear
|
||||
// that no webhooks are registered anymore
|
||||
delete webhookData.webhookId;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const bodyData = this.getBodyData();
|
||||
// getting bodyData as string, so need to JSON parse it to convert to an object
|
||||
return {
|
||||
workflowData: [this.helpers.returnJsonArray(JSON.parse(bodyData as any))],
|
||||
};
|
||||
}
|
||||
}
|
||||
69
packages/n8n/nodes/Formbricks/GenericFunctions.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { IHookFunctions, ILoadOptionsFunctions } from "n8n-core";
|
||||
import {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHttpRequestMethods,
|
||||
IHttpRequestOptions,
|
||||
INodePropertyOptions,
|
||||
JsonObject,
|
||||
NodeApiError,
|
||||
NodeOperationError,
|
||||
} from "n8n-workflow";
|
||||
|
||||
/**
|
||||
* Make an API request to Formbricks
|
||||
*/
|
||||
export async function apiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: object,
|
||||
query: IDataObject = {},
|
||||
option: IDataObject = {}
|
||||
): Promise<any> {
|
||||
const credentials = await this.getCredentials("formbricksApi");
|
||||
|
||||
let options: IHttpRequestOptions = {
|
||||
baseURL: `${credentials.host}/api/v1`,
|
||||
method,
|
||||
body,
|
||||
qs: query,
|
||||
url: resource,
|
||||
headers: {
|
||||
"x-Api-Key": credentials.apiKey,
|
||||
},
|
||||
};
|
||||
|
||||
if (!Object.keys(query).length) {
|
||||
delete options.qs;
|
||||
}
|
||||
|
||||
options = Object.assign({}, options, option);
|
||||
try {
|
||||
return await this.helpers.httpRequestWithAuthentication.call(this, "formbricksApi", options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the available surveys
|
||||
*/
|
||||
export async function getSurveys(this: ILoadOptionsFunctions): Promise<any> {
|
||||
const endpoint = "/surveys";
|
||||
const responseData = await apiRequest.call(this, "GET", endpoint, {});
|
||||
|
||||
if (!responseData.data) {
|
||||
throw new NodeOperationError(this.getNode(), "No data got returned");
|
||||
}
|
||||
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
for (const data of responseData.data) {
|
||||
returnData.push({
|
||||
name: data.name,
|
||||
value: data.id,
|
||||
});
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
75
packages/n8n/nodes/Formbricks/formbricks.svg
Normal file
@@ -0,0 +1,75 @@
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="500" height="500" fill="white"/>
|
||||
<path d="M90 334H218V398.716C218 433.667 189.667 462 154.716 462H153.284C118.333 462 90 433.667 90 398.716V334Z" fill="url(#paint0_linear_3927_2011)"/>
|
||||
<path d="M90 186H346.716C381.667 186 410 214.334 410 249.284V250.717C410 285.667 381.667 314 346.716 314H90V186Z" fill="url(#paint1_linear_3927_2011)"/>
|
||||
<path d="M90 101.284C90 66.333 118.333 38 153.284 38H346.716C381.667 38 410 66.333 410 101.284V102.716C410 137.667 381.667 166 346.716 166H90V101.284Z" fill="url(#paint2_linear_3927_2011)"/>
|
||||
<mask id="mask0_3927_2011" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="90" y="38" width="320" height="424">
|
||||
<path d="M90 334H218V398.716C218 433.667 189.667 462 154.716 462H153.284C118.333 462 90 433.667 90 398.716V334Z" fill="url(#paint3_linear_3927_2011)"/>
|
||||
<path d="M90 186H346.716C381.667 186 410 214.334 410 249.284V250.717C410 285.667 381.667 314 346.716 314H90V186Z" fill="url(#paint4_linear_3927_2011)"/>
|
||||
<path d="M90 101.284C90 66.333 118.333 38 153.284 38H346.716C381.667 38 410 66.333 410 101.284V102.716C410 137.667 381.667 166 346.716 166H90V101.284Z" fill="url(#paint5_linear_3927_2011)"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_3927_2011)">
|
||||
<g filter="url(#filter0_d_3927_2011)">
|
||||
<mask id="mask1_3927_2011" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="90" y="38" width="320" height="424">
|
||||
<path d="M90 334H218V398.716C218 433.667 189.667 462 154.716 462H153.284C118.333 462 90 433.667 90 398.716V334Z" fill="black" fill-opacity="0.1"/>
|
||||
<path d="M90 101.284C90 66.333 118.333 38 153.284 38H346.716C381.667 38 410 66.333 410 101.284V102.716C410 137.667 381.667 166 346.716 166H90V101.284Z" fill="black" fill-opacity="0.1"/>
|
||||
<path d="M90 186H346.716C381.667 186 410 214.334 410 249.284V250.717C410 285.667 381.667 314 346.716 314H90V186Z" fill="black" fill-opacity="0.1"/>
|
||||
</mask>
|
||||
<g mask="url(#mask1_3927_2011)">
|
||||
<path d="M96.7149 -72.2506C146.856 -121.187 273.999 -72.2506 273.999 -72.2506H96.7149C84.3998 -60.2313 76.7298 -42.3079 76.7298 -16.3051C76.7298 115.567 219.58 163.522 219.58 255.433C219.58 345.407 82.6888 400.915 76.9176 523.174H273.999C273.999 523.174 76.7298 659.043 76.7298 531.166C76.7298 528.471 76.7933 525.807 76.9176 523.174H-10.0007L7.00526 -72.2506H96.7149Z" fill="black" fill-opacity="0.1"/>
|
||||
</g>
|
||||
</g>
|
||||
<g filter="url(#filter1_f_3927_2011)">
|
||||
<circle cx="50.0005" cy="406" r="120" fill="#00C4B8"/>
|
||||
</g>
|
||||
<g filter="url(#filter2_f_3927_2011)">
|
||||
<circle cx="50.0005" cy="102" r="120" fill="#00C4B8"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3927_2011" x="83.6716" y="0.0298538" width="259.94" height="499.94" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="31.6418"/>
|
||||
<feGaussianBlur stdDeviation="18.9851"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3927_2011"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3927_2011" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_3927_2011" x="-133.283" y="222.717" width="366.567" height="366.567" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="31.6418" result="effect1_foregroundBlur_3927_2011"/>
|
||||
</filter>
|
||||
<filter id="filter2_f_3927_2011" x="-133.283" y="-81.2831" width="366.567" height="366.567" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="31.6418" result="effect1_foregroundBlur_3927_2011"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_3927_2011" x1="218.557" y1="395.681" x2="89.989" y2="396.2" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00E6CA"/>
|
||||
<stop offset="1" stop-color="#00C4B8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_3927_2011" x1="411.391" y1="247.682" x2="90" y2="250.928" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00E6CA"/>
|
||||
<stop offset="1" stop-color="#00C4B8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_3927_2011" x1="411.391" y1="99.6812" x2="90" y2="102.928" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00E6CA"/>
|
||||
<stop offset="1" stop-color="#00C4B8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_3927_2011" x1="218.557" y1="395.681" x2="89.989" y2="396.2" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00FFE1"/>
|
||||
<stop offset="1" stop-color="#01E0C6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_3927_2011" x1="411.391" y1="247.682" x2="90" y2="250.928" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00FFE1"/>
|
||||
<stop offset="1" stop-color="#01E0C6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_3927_2011" x1="411.391" y1="99.6812" x2="90" y2="102.928" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00FFE1"/>
|
||||
<stop offset="1" stop-color="#01E0C6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
55
packages/n8n/package.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "@formbricks/n8n-nodes-formbricks",
|
||||
"version": "0.1.0",
|
||||
"description": "A n8n node to connect Formbricks and send survey data to hundreds of other apps.",
|
||||
"keywords": [
|
||||
"n8n-community-node-package",
|
||||
"n8n",
|
||||
"trigger",
|
||||
"Formbricks",
|
||||
"n8n-node",
|
||||
"surveys",
|
||||
"experience management"
|
||||
],
|
||||
"license": "MIT",
|
||||
"homepage": "https://formbricks.com",
|
||||
"author": {
|
||||
"name": "PratikAwaik",
|
||||
"email": "pratikawaik125@gmail.com"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/formbricks/formbricks"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && gulp build:icons",
|
||||
"dev": "tsc --watch",
|
||||
"format": "prettier nodes credentials --write",
|
||||
"lint": "eslint nodes credentials package.json",
|
||||
"lintfix": "eslint nodes credentials package.json --fix",
|
||||
"prepublishOnly": "npm run build && npm run lint -c .eslintrc.prepublish.js nodes credentials package.json"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"n8n": {
|
||||
"n8nNodesApiVersion": 1,
|
||||
"credentials": [
|
||||
"dist/credentials/FormbricksApi.credentials.js"
|
||||
],
|
||||
"nodes": [
|
||||
"dist/nodes/Formbricks/Formbricks.node.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/request-promise-native": "~1.0.15",
|
||||
"@typescript-eslint/parser": "~5.45",
|
||||
"eslint-plugin-n8n-nodes-base": "^1.11.0",
|
||||
"gulp": "^4.0.2",
|
||||
"n8n-core": "*",
|
||||
"n8n-workflow": "*",
|
||||
"typescript": "~4.8.4"
|
||||
}
|
||||
}
|
||||
3765
packages/n8n/pnpm-lock.yaml
generated
Normal file
0
packages/n8n/pnpm-workspace.yaml
Normal file
30
packages/n8n/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2019",
|
||||
"lib": ["es2019", "es2020", "es2022.error"],
|
||||
"removeComments": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictNullChecks": true,
|
||||
"preserveConstEnums": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"incremental": true,
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist/",
|
||||
},
|
||||
"include": [
|
||||
"credentials/**/*",
|
||||
"nodes/**/*",
|
||||
"nodes/**/*.json",
|
||||
"package.json",
|
||||
],
|
||||
}
|
||||
83
packages/n8n/tslint.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"linterOptions": {
|
||||
"exclude": ["node_modules/**/*"]
|
||||
},
|
||||
"defaultSeverity": "error",
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"array-type": [true, "array-simple"],
|
||||
"arrow-return-shorthand": true,
|
||||
"ban": [
|
||||
true,
|
||||
{
|
||||
"name": "Array",
|
||||
"message": "tsstyle#array-constructor"
|
||||
}
|
||||
],
|
||||
"ban-types": [
|
||||
true,
|
||||
["Object", "Use {} instead."],
|
||||
["String", "Use 'string' instead."],
|
||||
["Number", "Use 'number' instead."],
|
||||
["Boolean", "Use 'boolean' instead."]
|
||||
],
|
||||
"class-name": true,
|
||||
"curly": [true, "ignore-same-line"],
|
||||
"forin": true,
|
||||
"jsdoc-format": true,
|
||||
"label-position": true,
|
||||
"indent": [true, "tabs", 2],
|
||||
"member-access": [true, "no-public"],
|
||||
"new-parens": true,
|
||||
"no-angle-bracket-type-assertion": true,
|
||||
"no-any": true,
|
||||
"no-arg": true,
|
||||
"no-conditional-assignment": true,
|
||||
"no-construct": true,
|
||||
"no-debugger": true,
|
||||
"no-default-export": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-inferrable-types": true,
|
||||
"ordered-imports": [
|
||||
true,
|
||||
{
|
||||
"import-sources-order": "any",
|
||||
"named-imports-order": "case-insensitive"
|
||||
}
|
||||
],
|
||||
"no-namespace": [true, "allow-declarations"],
|
||||
"no-reference": true,
|
||||
"no-string-throw": true,
|
||||
"no-unused-expression": true,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-shorthand": true,
|
||||
"only-arrow-functions": [true, "allow-declarations", "allow-named-functions"],
|
||||
"prefer-const": true,
|
||||
"radix": true,
|
||||
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
||||
"switch-default": true,
|
||||
"trailing-comma": [
|
||||
true,
|
||||
{
|
||||
"multiline": {
|
||||
"objects": "always",
|
||||
"arrays": "always",
|
||||
"functions": "always",
|
||||
"typeLiterals": "ignore"
|
||||
},
|
||||
"esSpecCompliant": true
|
||||
}
|
||||
],
|
||||
"triple-equals": [true, "allow-null-check"],
|
||||
"use-isnan": true,
|
||||
"quotes": ["error", "single"],
|
||||
"variable-name": [
|
||||
true,
|
||||
"check-format",
|
||||
"ban-keywords",
|
||||
"allow-leading-underscore",
|
||||
"allow-trailing-underscore"
|
||||
]
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||
55
pnpm-lock.yaml
generated
@@ -19,7 +19,7 @@ importers:
|
||||
version: 3.12.7
|
||||
turbo:
|
||||
specifier: latest
|
||||
version: 1.10.7
|
||||
version: 1.10.12
|
||||
|
||||
apps/demo:
|
||||
dependencies:
|
||||
@@ -427,7 +427,7 @@ importers:
|
||||
version: 8.10.0(eslint@8.46.0)
|
||||
eslint-config-turbo:
|
||||
specifier: latest
|
||||
version: 1.8.8(eslint@8.46.0)
|
||||
version: 1.10.12(eslint@8.46.0)
|
||||
eslint-plugin-react:
|
||||
specifier: 7.33.1
|
||||
version: 7.33.1(eslint@8.46.0)
|
||||
@@ -10112,13 +10112,13 @@ packages:
|
||||
eslint: 8.46.0
|
||||
dev: true
|
||||
|
||||
/eslint-config-turbo@1.8.8(eslint@8.46.0):
|
||||
resolution: {integrity: sha512-+yT22sHOT5iC1sbBXfLIdXfbZuiv9bAyOXsxTxFCWelTeFFnANqmuKB3x274CFvf7WRuZ/vYP/VMjzU9xnFnxA==}
|
||||
/eslint-config-turbo@1.10.12(eslint@8.46.0):
|
||||
resolution: {integrity: sha512-z3jfh+D7UGYlzMWGh+Kqz++hf8LOE96q3o5R8X4HTjmxaBWlLAWG+0Ounr38h+JLR2TJno0hU9zfzoPNkR9BdA==}
|
||||
peerDependencies:
|
||||
eslint: '>6.6.0'
|
||||
dependencies:
|
||||
eslint: 8.46.0
|
||||
eslint-plugin-turbo: 1.8.8(eslint@8.46.0)
|
||||
eslint-plugin-turbo: 1.10.12(eslint@8.46.0)
|
||||
dev: true
|
||||
|
||||
/eslint-import-resolver-node@0.3.6:
|
||||
@@ -10306,11 +10306,12 @@ packages:
|
||||
semver: 6.3.1
|
||||
string.prototype.matchall: 4.0.8
|
||||
|
||||
/eslint-plugin-turbo@1.8.8(eslint@8.46.0):
|
||||
resolution: {integrity: sha512-zqyTIvveOY4YU5jviDWw9GXHd4RiKmfEgwsjBrV/a965w0PpDwJgEUoSMB/C/dU310Sv9mF3DSdEjxjJLaw6rA==}
|
||||
/eslint-plugin-turbo@1.10.12(eslint@8.46.0):
|
||||
resolution: {integrity: sha512-uNbdj+ohZaYo4tFJ6dStRXu2FZigwulR1b3URPXe0Q8YaE7thuekKNP+54CHtZPH9Zey9dmDx5btAQl9mfzGOw==}
|
||||
peerDependencies:
|
||||
eslint: '>6.6.0'
|
||||
dependencies:
|
||||
dotenv: 16.0.3
|
||||
eslint: 8.46.0
|
||||
dev: true
|
||||
|
||||
@@ -20281,65 +20282,65 @@ packages:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
/turbo-darwin-64@1.10.7:
|
||||
resolution: {integrity: sha512-N2MNuhwrl6g7vGuz4y3fFG2aR1oCs0UZ5HKl8KSTn/VC2y2YIuLGedQ3OVbo0TfEvygAlF3QGAAKKtOCmGPNKA==}
|
||||
/turbo-darwin-64@1.10.12:
|
||||
resolution: {integrity: sha512-vmDfGVPl5/aFenAbOj3eOx3ePNcWVUyZwYr7taRl0ZBbmv2TzjRiFotO4vrKCiTVnbqjQqAFQWY2ugbqCI1kOQ==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo-darwin-arm64@1.10.7:
|
||||
resolution: {integrity: sha512-WbJkvjU+6qkngp7K4EsswOriO3xrNQag7YEGRtfLoDdMTk4O4QTeU6sfg2dKfDsBpTidTvEDwgIYJhYVGzrz9Q==}
|
||||
/turbo-darwin-arm64@1.10.12:
|
||||
resolution: {integrity: sha512-3JliEESLNX2s7g54SOBqqkqJ7UhcOGkS0ywMr5SNuvF6kWVTbuUq7uBU/sVbGq8RwvK1ONlhPvJne5MUqBCTCQ==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo-linux-64@1.10.7:
|
||||
resolution: {integrity: sha512-x1CF2CDP1pDz/J8/B2T0hnmmOQI2+y11JGIzNP0KtwxDM7rmeg3DDTtDM/9PwGqfPotN9iVGgMiMvBuMFbsLhg==}
|
||||
/turbo-linux-64@1.10.12:
|
||||
resolution: {integrity: sha512-siYhgeX0DidIfHSgCR95b8xPee9enKSOjCzx7EjTLmPqPaCiVebRYvbOIYdQWRqiaKh9yfhUtFmtMOMScUf1gg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo-linux-arm64@1.10.7:
|
||||
resolution: {integrity: sha512-JtnBmaBSYbs7peJPkXzXxsRGSGBmBEIb6/kC8RRmyvPAMyqF8wIex0pttsI+9plghREiGPtRWv/lfQEPRlXnNQ==}
|
||||
/turbo-linux-arm64@1.10.12:
|
||||
resolution: {integrity: sha512-K/ZhvD9l4SslclaMkTiIrnfcACgos79YcAo4kwc8bnMQaKuUeRpM15sxLpZp3xDjDg8EY93vsKyjaOhdFG2UbA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo-windows-64@1.10.7:
|
||||
resolution: {integrity: sha512-7A/4CByoHdolWS8dg3DPm99owfu1aY/W0V0+KxFd0o2JQMTQtoBgIMSvZesXaWM57z3OLsietFivDLQPuzE75w==}
|
||||
/turbo-windows-64@1.10.12:
|
||||
resolution: {integrity: sha512-7FSgSwvktWDNOqV65l9AbZwcoueAILeE4L7JvjauNASAjjbuzXGCEq5uN8AQU3U5BOFj4TdXrVmO2dX+lLu8Zg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo-windows-arm64@1.10.7:
|
||||
resolution: {integrity: sha512-D36K/3b6+hqm9IBAymnuVgyePktwQ+F0lSXr2B9JfAdFPBktSqGmp50JNC7pahxhnuCLj0Vdpe9RqfnJw5zATA==}
|
||||
/turbo-windows-arm64@1.10.12:
|
||||
resolution: {integrity: sha512-gCNXF52dwom1HLY9ry/cneBPOKTBHhzpqhMylcyvJP0vp9zeMQQkt6yjYv+6QdnmELC92CtKNp2FsNZo+z0pyw==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/turbo@1.10.7:
|
||||
resolution: {integrity: sha512-xm0MPM28TWx1e6TNC3wokfE5eaDqlfi0G24kmeHupDUZt5Wd0OzHFENEHMPqEaNKJ0I+AMObL6nbSZonZBV2HA==}
|
||||
/turbo@1.10.12:
|
||||
resolution: {integrity: sha512-WM3+jTfQWnB9W208pmP4oeehZcC6JQNlydb/ZHMRrhmQa+htGhWLCzd6Q9rLe0MwZLPpSPFV2/bN5egCLyoKjQ==}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
turbo-darwin-64: 1.10.7
|
||||
turbo-darwin-arm64: 1.10.7
|
||||
turbo-linux-64: 1.10.7
|
||||
turbo-linux-arm64: 1.10.7
|
||||
turbo-windows-64: 1.10.7
|
||||
turbo-windows-arm64: 1.10.7
|
||||
turbo-darwin-64: 1.10.12
|
||||
turbo-darwin-arm64: 1.10.12
|
||||
turbo-linux-64: 1.10.12
|
||||
turbo-linux-arm64: 1.10.12
|
||||
turbo-windows-64: 1.10.12
|
||||
turbo-windows-arm64: 1.10.12
|
||||
dev: true
|
||||
|
||||
/tween-functions@1.2.0:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
packages:
|
||||
- "apps/*"
|
||||
- "packages/*"
|
||||
- "!packages/n8n"
|
||||
|
||||