mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 21:07:28 -08:00
🔀 Merge branch 'guilhermeagirardi-master'
This commit is contained in:
commit
0b1263d815
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -11,3 +11,4 @@ google-generated-credentials.json
|
||||||
_START_PACKAGE
|
_START_PACKAGE
|
||||||
.env
|
.env
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
|
@ -175,6 +175,31 @@ docker run -it --rm \
|
||||||
A full working setup with docker-compose can be found [here](https://github.com/n8n-io/n8n/blob/master/docker/compose/withPostgres/README.md)
|
A full working setup with docker-compose can be found [here](https://github.com/n8n-io/n8n/blob/master/docker/compose/withPostgres/README.md)
|
||||||
|
|
||||||
|
|
||||||
|
#### Use with MySQL
|
||||||
|
|
||||||
|
Replace the following placeholders with the actual data:
|
||||||
|
- MYSQLDB_DATABASE
|
||||||
|
- MYSQLDB_HOST
|
||||||
|
- MYSQLDB_PASSWORD
|
||||||
|
- MYSQLDB_PORT
|
||||||
|
- MYSQLDB_USER
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -it --rm \
|
||||||
|
--name n8n \
|
||||||
|
-p 5678:5678 \
|
||||||
|
-e DB_TYPE=mysqldb \
|
||||||
|
-e DB_MYSQLDB_DATABASE=<MYSQLDB_DATABASE> \
|
||||||
|
-e DB_MYSQLDB_HOST=<MYSQLDB_HOST> \
|
||||||
|
-e DB_MYSQLDB_PORT=<MYSQLDB_PORT> \
|
||||||
|
-e DB_MYSQLDB_USER=<MYSQLDB_USER> \
|
||||||
|
-e DB_MYSQLDB_PASSWORD=<MYSQLDB_PASSWORD> \
|
||||||
|
-v ~/.n8n:/root/.n8n \
|
||||||
|
n8nio/n8n \
|
||||||
|
n8n start
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Passing Sensitive Data via File
|
## Passing Sensitive Data via File
|
||||||
|
|
||||||
To avoid passing sensitive information via environment variables "_FILE" may be
|
To avoid passing sensitive information via environment variables "_FILE" may be
|
||||||
|
|
|
@ -51,6 +51,30 @@ export DB_POSTGRESDB_PASSWORD=n8n
|
||||||
n8n start
|
n8n start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MySQL
|
||||||
|
|
||||||
|
The compatibility with MySQL was tested, even so, it is advisable to observe the operation of the application with this DB, as it is a new option, recently added. If you spot any problems, feel free to submit a PR.
|
||||||
|
|
||||||
|
To use MySQL as database you can provide the following environment variables:
|
||||||
|
- `DB_TYPE=mysqldb`
|
||||||
|
- `DB_MYSQLDB_DATABASE` (default: 'n8n')
|
||||||
|
- `DB_MYSQLDB_HOST` (default: 'localhost')
|
||||||
|
- `DB_MYSQLDB_PORT` (default: 3306)
|
||||||
|
- `DB_MYSQLDB_USER` (default: 'root')
|
||||||
|
- `DB_MYSQLDB_PASSWORD` (default: empty)
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DB_TYPE=mysqldb
|
||||||
|
export DB_MYSQLDB_DATABASE=n8n
|
||||||
|
export DB_MYSQLDB_HOST=mysqldb
|
||||||
|
export DB_MYSQLDB_PORT=3306
|
||||||
|
export DB_MYSQLDB_USER=n8n
|
||||||
|
export DB_MYSQLDB_PASSWORD=n8n
|
||||||
|
|
||||||
|
n8n start
|
||||||
|
```
|
||||||
|
|
||||||
## SQLite
|
## SQLite
|
||||||
|
|
||||||
The default database which gets used if no other one is defined.
|
The default database which gets used if no other one is defined.
|
||||||
|
|
|
@ -8,7 +8,7 @@ const config = convict({
|
||||||
database: {
|
database: {
|
||||||
type: {
|
type: {
|
||||||
doc: 'Type of database to use',
|
doc: 'Type of database to use',
|
||||||
format: ['sqlite', 'mongodb', 'postgresdb'],
|
format: ['sqlite', 'mongodb', 'mysqldb', 'postgresdb'],
|
||||||
default: 'sqlite',
|
default: 'sqlite',
|
||||||
env: 'DB_TYPE'
|
env: 'DB_TYPE'
|
||||||
},
|
},
|
||||||
|
@ -52,6 +52,38 @@ const config = convict({
|
||||||
env: 'DB_POSTGRESDB_USER'
|
env: 'DB_POSTGRESDB_USER'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mysqldb: {
|
||||||
|
database: {
|
||||||
|
doc: 'MySQL Database',
|
||||||
|
format: String,
|
||||||
|
default: 'n8n',
|
||||||
|
env: 'DB_MYSQLDB_DATABASE'
|
||||||
|
},
|
||||||
|
host: {
|
||||||
|
doc: 'MySQL Host',
|
||||||
|
format: String,
|
||||||
|
default: 'localhost',
|
||||||
|
env: 'DB_MYSQLDB_HOST'
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
doc: 'MySQL Password',
|
||||||
|
format: String,
|
||||||
|
default: '',
|
||||||
|
env: 'DB_MYSQLDB_PASSWORD'
|
||||||
|
},
|
||||||
|
port: {
|
||||||
|
doc: 'MySQL Port',
|
||||||
|
format: Number,
|
||||||
|
default: 3306,
|
||||||
|
env: 'DB_MYSQLDB_PORT'
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
doc: 'MySQL User',
|
||||||
|
format: String,
|
||||||
|
default: 'root',
|
||||||
|
env: 'DB_MYSQLDB_USER'
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
executions: {
|
executions: {
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
"localtunnel": "^2.0.0",
|
"localtunnel": "^2.0.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"mongodb": "^3.2.3",
|
"mongodb": "^3.2.3",
|
||||||
|
"mysql2": "^2.0.1",
|
||||||
"n8n-core": "~0.24.0",
|
"n8n-core": "~0.24.0",
|
||||||
"n8n-editor-ui": "~0.35.0",
|
"n8n-editor-ui": "~0.35.0",
|
||||||
"n8n-nodes-base": "~0.47.0",
|
"n8n-nodes-base": "~0.47.0",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
MongoDb,
|
MongoDb,
|
||||||
PostgresDb,
|
PostgresDb,
|
||||||
SQLite,
|
SQLite,
|
||||||
|
MySQLDb,
|
||||||
} from './databases';
|
} from './databases';
|
||||||
|
|
||||||
export let collections: IDatabaseCollections = {
|
export let collections: IDatabaseCollections = {
|
||||||
|
@ -36,33 +37,53 @@ export async function init(synchronize?: boolean): Promise<IDatabaseCollections>
|
||||||
let connectionOptions: ConnectionOptions;
|
let connectionOptions: ConnectionOptions;
|
||||||
|
|
||||||
let dbNotExistError: string | undefined;
|
let dbNotExistError: string | undefined;
|
||||||
if (dbType === 'mongodb') {
|
switch (dbType) {
|
||||||
entities = MongoDb;
|
case 'mongodb':
|
||||||
connectionOptions = {
|
entities = MongoDb;
|
||||||
type: 'mongodb',
|
connectionOptions = {
|
||||||
url: await GenericHelpers.getConfigValue('database.mongodb.connectionUrl') as string,
|
type: 'mongodb',
|
||||||
useNewUrlParser: true,
|
url: await GenericHelpers.getConfigValue('database.mongodb.connectionUrl') as string,
|
||||||
};
|
useNewUrlParser: true,
|
||||||
} else if (dbType === 'postgresdb') {
|
};
|
||||||
dbNotExistError = 'does not exist';
|
break;
|
||||||
entities = PostgresDb;
|
|
||||||
connectionOptions = {
|
case 'postgresdb':
|
||||||
type: 'postgres',
|
dbNotExistError = 'does not exist';
|
||||||
database: await GenericHelpers.getConfigValue('database.postgresdb.database') as string,
|
entities = PostgresDb;
|
||||||
host: await GenericHelpers.getConfigValue('database.postgresdb.host') as string,
|
connectionOptions = {
|
||||||
password: await GenericHelpers.getConfigValue('database.postgresdb.password') as string,
|
type: 'postgres',
|
||||||
port: await GenericHelpers.getConfigValue('database.postgresdb.port') as number,
|
database: await GenericHelpers.getConfigValue('database.postgresdb.database') as string,
|
||||||
username: await GenericHelpers.getConfigValue('database.postgresdb.user') as string,
|
host: await GenericHelpers.getConfigValue('database.postgresdb.host') as string,
|
||||||
};
|
password: await GenericHelpers.getConfigValue('database.postgresdb.password') as string,
|
||||||
} else if (dbType === 'sqlite') {
|
port: await GenericHelpers.getConfigValue('database.postgresdb.port') as number,
|
||||||
dbNotExistError = 'no such table:';
|
username: await GenericHelpers.getConfigValue('database.postgresdb.user') as string,
|
||||||
entities = SQLite;
|
};
|
||||||
connectionOptions = {
|
break;
|
||||||
type: 'sqlite',
|
|
||||||
database: path.join(n8nFolder, 'database.sqlite'),
|
case 'mysqldb':
|
||||||
};
|
dbNotExistError = 'does not exist';
|
||||||
} else {
|
entities = MySQLDb;
|
||||||
throw new Error(`The database "${dbType}" is currently not supported!`);
|
connectionOptions = {
|
||||||
|
type: 'mysql',
|
||||||
|
database: await GenericHelpers.getConfigValue('database.mysqldb.database') as string,
|
||||||
|
host: await GenericHelpers.getConfigValue('database.mysqldb.host') as string,
|
||||||
|
password: await GenericHelpers.getConfigValue('database.mysqldb.password') as string,
|
||||||
|
port: await GenericHelpers.getConfigValue('database.mysqldb.port') as number,
|
||||||
|
username: await GenericHelpers.getConfigValue('database.mysqldb.user') as string
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sqlite':
|
||||||
|
dbNotExistError = 'no such table:';
|
||||||
|
entities = SQLite;
|
||||||
|
connectionOptions = {
|
||||||
|
type: 'sqlite',
|
||||||
|
database: path.join(n8nFolder, 'database.sqlite'),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(`The database "${dbType}" is currently not supported!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(connectionOptions, {
|
Object.assign(connectionOptions, {
|
||||||
|
|
|
@ -87,7 +87,7 @@ export interface ICredentialsDecryptedResponse extends ICredentialsDecryptedDb {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DatabaseType = 'mongodb' | 'postgresdb' | 'sqlite';
|
export type DatabaseType = 'mongodb' | 'postgresdb' | 'mysqldb' | 'sqlite';
|
||||||
export type SaveExecutionDataType = 'all' | 'none';
|
export type SaveExecutionDataType = 'all' | 'none';
|
||||||
|
|
||||||
export interface IExecutionBase {
|
export interface IExecutionBase {
|
||||||
|
|
|
@ -205,8 +205,6 @@ export class TestWebhooks {
|
||||||
let workflow: Workflow;
|
let workflow: Workflow;
|
||||||
const workflows: Workflow[] = [];
|
const workflows: Workflow[] = [];
|
||||||
for (const webhookKey of Object.keys(this.testWebhookData)) {
|
for (const webhookKey of Object.keys(this.testWebhookData)) {
|
||||||
console.log('webhookKey: ' + webhookKey);
|
|
||||||
|
|
||||||
workflowData = this.testWebhookData[webhookKey].workflowData;
|
workflowData = this.testWebhookData[webhookKey].workflowData;
|
||||||
workflow = new Workflow(workflowData.id.toString(), workflowData.nodes, workflowData.connections, workflowData.active, nodeTypes, workflowData.staticData, workflowData.settings);
|
workflow = new Workflow(workflowData.id.toString(), workflowData.nodes, workflowData.connections, workflowData.active, nodeTypes, workflowData.staticData, workflowData.settings);
|
||||||
workflows.push();
|
workflows.push();
|
||||||
|
@ -214,11 +212,8 @@ export class TestWebhooks {
|
||||||
|
|
||||||
return this.activeWebhooks.removeAll(workflows);
|
return this.activeWebhooks.removeAll(workflows);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let testWebhooksInstance: TestWebhooks | undefined;
|
let testWebhooksInstance: TestWebhooks | undefined;
|
||||||
|
|
||||||
export function getInstance(): TestWebhooks {
|
export function getInstance(): TestWebhooks {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import * as MongoDb from './mongodb';
|
import * as MongoDb from './mongodb';
|
||||||
import * as PostgresDb from './postgresdb';
|
import * as PostgresDb from './postgresdb';
|
||||||
import * as SQLite from './sqlite';
|
import * as SQLite from './sqlite';
|
||||||
|
import * as MySQLDb from './mysqldb';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
MongoDb,
|
MongoDb,
|
||||||
PostgresDb,
|
PostgresDb,
|
||||||
SQLite,
|
SQLite,
|
||||||
|
MySQLDb,
|
||||||
};
|
};
|
||||||
|
|
44
packages/cli/src/databases/mysqldb/CredentialsEntity.ts
Normal file
44
packages/cli/src/databases/mysqldb/CredentialsEntity.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import {
|
||||||
|
ICredentialNodeAccess,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ICredentialsDb,
|
||||||
|
} from '../../';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class CredentialsEntity implements ICredentialsDb {
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
length: 128
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column('text')
|
||||||
|
data: string;
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({
|
||||||
|
length: 32
|
||||||
|
})
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
@Column('json')
|
||||||
|
nodesAccess: ICredentialNodeAccess[];
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
51
packages/cli/src/databases/mysqldb/ExecutionEntity.ts
Normal file
51
packages/cli/src/databases/mysqldb/ExecutionEntity.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import {
|
||||||
|
WorkflowExecuteMode,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IExecutionFlattedDb,
|
||||||
|
IWorkflowDb,
|
||||||
|
} from '../../';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class ExecutionEntity implements IExecutionFlattedDb {
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column('text')
|
||||||
|
data: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
finished: boolean;
|
||||||
|
|
||||||
|
@Column('varchar')
|
||||||
|
mode: WorkflowExecuteMode;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
retryOf: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
retrySuccessId: string;
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
startedAt: Date;
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
stoppedAt: Date;
|
||||||
|
|
||||||
|
@Column('json')
|
||||||
|
workflowData: IWorkflowDb;
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({ nullable: true })
|
||||||
|
workflowId: string;
|
||||||
|
}
|
55
packages/cli/src/databases/mysqldb/WorkflowEntity.ts
Normal file
55
packages/cli/src/databases/mysqldb/WorkflowEntity.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import {
|
||||||
|
IConnections,
|
||||||
|
IDataObject,
|
||||||
|
INode,
|
||||||
|
IWorkflowSettings,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IWorkflowDb,
|
||||||
|
} from '../../';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class WorkflowEntity implements IWorkflowDb {
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
length: 128
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
active: boolean;
|
||||||
|
|
||||||
|
@Column('json')
|
||||||
|
nodes: INode[];
|
||||||
|
|
||||||
|
@Column('json')
|
||||||
|
connections: IConnections;
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@Column('datetime')
|
||||||
|
updatedAt: Date;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'json',
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
settings?: IWorkflowSettings;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'json',
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
staticData?: IDataObject;
|
||||||
|
}
|
3
packages/cli/src/databases/mysqldb/index.ts
Normal file
3
packages/cli/src/databases/mysqldb/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './CredentialsEntity';
|
||||||
|
export * from './ExecutionEntity';
|
||||||
|
export * from './WorkflowEntity';
|
|
@ -17,7 +17,7 @@
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"dev": "npm run serve",
|
"dev": "npm run serve",
|
||||||
"lint": "vue-cli-service lint",
|
"lint": "vue-cli-service lint",
|
||||||
"serve": "VUE_APP_URL_BASE_API=http://localhost:5678/ vue-cli-service serve",
|
"serve": "cross-env VUE_APP_URL_BASE_API=http://localhost:5678/ vue-cli-service serve",
|
||||||
"test": "npm run test:unit",
|
"test": "npm run test:unit",
|
||||||
"tslint": "tslint -p tsconfig.json -c tslint.json",
|
"tslint": "tslint -p tsconfig.json -c tslint.json",
|
||||||
"test:e2e": "vue-cli-service test:e2e",
|
"test:e2e": "vue-cli-service test:e2e",
|
||||||
|
|
Loading…
Reference in a new issue