chore: move n8n-node to own repository (#1662)

This commit is contained in:
Matti Nannt
2023-11-21 13:09:53 +01:00
committed by GitHub
parent 94bf1fd6fe
commit 6db76d094b
18 changed files with 32 additions and 2902 deletions

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,8 +0,0 @@
node_modules
.DS_Store
.tmp
tmp
dist
npm-debug.log*
yarn.lock
.vscode/launch.json

View File

@@ -1,2 +0,0 @@
.DS_Store
*.tsbuildinfo

View File

@@ -1,7 +0,0 @@
# @formbricks/n8n-nodes-formbricks
## 0.2.0
### Minor Changes
- aa79c4c3: Add new n8n Integration for Formbricks; huge thanks to @PratikAwaik

View File

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

View File

@@ -1,39 +0,0 @@
# 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)

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

View File

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

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -1,55 +0,0 @@
{
"name": "@formbricks/n8n-nodes-formbricks",
"version": "0.2.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",
"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": "pnpm run build && pnpm 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.21",
"@types/request-promise-native": "~1.0.21",
"@typescript-eslint/parser": "~6.12",
"eslint-plugin-n8n-nodes-base": "^1.16.1",
"gulp": "^4.0.2",
"n8n-core": "legacy",
"n8n-workflow": "legacy"
}
}

View File

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

2254
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff