Add Pre-Commit Hook for linting & formatting (#767)

* add pre-commit hook for linting & formatting

* add husky

* update n8n package json, update package-lock file
This commit is contained in:
Matti Nannt
2023-09-04 15:45:18 +09:00
committed by GitHub
parent 5e640b1c54
commit 8a46b2c4be
33 changed files with 2290 additions and 4358 deletions

4
.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm lint-staged

View File

@@ -1,5 +1,5 @@
{
"name": "turbo",
"name": "formbricks",
"version": "0.0.0",
"private": true,
"workspaces": [
@@ -19,19 +19,35 @@
"db:push": "turbo run db:push",
"go": "turbo run go --concurrency 16",
"dev": "turbo run dev --parallel",
"pre-commit": "lint-staged",
"start": "turbo run start --parallel",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"generate": "turbo run generate",
"lint": "turbo run lint",
"release": "turbo run build --filter=js... && turbo run build --filter=n8n... && changeset publish",
"test": "turbo run test"
"release": "turbo run build --filter=js... && turbo run build --filter=n8n-node... && changeset publish",
"test": "turbo run test",
"prepare": "husky install"
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"husky": "^8.0.3",
"lint-staged": "^14.0.1",
"rimraf": "^5.0.1",
"tsx": "^3.12.7",
"turbo": "latest"
},
"lint-staged": {
"(apps|packages)/**/*.{js,ts,jsx,tsx}": [
"prettier --write",
"eslint --fix"
],
"*.json": [
"prettier --write"
],
"packages/database/schema.prisma": [
"prisma format"
]
},
"engines": {
"node": ">=16.0.0"
},

View 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",
},
},
],
};

View 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",
},
},
],
};

View 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",
},
};
}

View 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));
}

View 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/"
}
]
}
}

View 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))],
};
}
}

View 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;
}

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -24,11 +24,12 @@
"main": "index.js",
"scripts": {
"build": "tsc && gulp build:icons",
"clean": "rimraf .turbo node_modules dist",
"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"
"prepublishOnly": "pnpm run build && pnpm run lint -c .eslintrc.prepublish.js nodes credentials package.json"
},
"files": [
"dist"
@@ -43,13 +44,11 @@
]
},
"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"
"n8n-core": "^1.1.1",
"n8n-workflow": "^1.1.1"
}
}

View File

@@ -0,0 +1,25 @@
{
"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"]
}

View 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": []
}

View File

@@ -1,20 +0,0 @@
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

View File

@@ -1,53 +0,0 @@
/**
* @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",
},
},
],
};

View File

@@ -1,16 +0,0 @@
/**
* @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',
},
},
],
};

View File

@@ -1,7 +0,0 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode",
]
}

View File

@@ -1,40 +0,0 @@
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",
},
};
}

View File

@@ -1,16 +0,0 @@
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));
}

View File

@@ -1,18 +0,0 @@
{
"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/"
}
]
}
}

View File

@@ -1,155 +0,0 @@
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))],
};
}
}

View File

@@ -1,69 +0,0 @@
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
{
"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",
],
}

View File

@@ -1,83 +0,0 @@
{
"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": []
}

1866
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff