mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(core): Add migration to create model for folders feature (#13060)
This commit is contained in:
parent
aedea7a76c
commit
03f4ed8445
45
packages/cli/src/databases/entities/folder.ts
Normal file
45
packages/cli/src/databases/entities/folder.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
|
JoinTable,
|
||||||
|
ManyToMany,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
} from '@n8n/typeorm';
|
||||||
|
|
||||||
|
import { WithTimestampsAndStringId } from './abstract-entity';
|
||||||
|
import { Project } from './project';
|
||||||
|
import { TagEntity } from './tag-entity';
|
||||||
|
import { type WorkflowEntity } from './workflow-entity';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Folder extends WithTimestampsAndStringId {
|
||||||
|
@Column()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Folder, { nullable: true })
|
||||||
|
@JoinColumn({ name: 'parentFolderId' })
|
||||||
|
parentFolder: Folder | null;
|
||||||
|
|
||||||
|
@ManyToOne(() => Project)
|
||||||
|
@JoinColumn({ name: 'projectId' })
|
||||||
|
project: Project;
|
||||||
|
|
||||||
|
@OneToMany('WorkflowEntity', 'parentFolder')
|
||||||
|
workflows: WorkflowEntity[];
|
||||||
|
|
||||||
|
@ManyToMany(() => TagEntity)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'folder_tag',
|
||||||
|
joinColumn: {
|
||||||
|
name: 'folderId',
|
||||||
|
referencedColumnName: 'id',
|
||||||
|
},
|
||||||
|
inverseJoinColumn: {
|
||||||
|
name: 'tagId',
|
||||||
|
referencedColumnName: 'id',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
tags: TagEntity[];
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import { ExecutionAnnotation } from './execution-annotation.ee';
|
||||||
import { ExecutionData } from './execution-data';
|
import { ExecutionData } from './execution-data';
|
||||||
import { ExecutionEntity } from './execution-entity';
|
import { ExecutionEntity } from './execution-entity';
|
||||||
import { ExecutionMetadata } from './execution-metadata';
|
import { ExecutionMetadata } from './execution-metadata';
|
||||||
|
import { Folder } from './folder';
|
||||||
import { InstalledNodes } from './installed-nodes';
|
import { InstalledNodes } from './installed-nodes';
|
||||||
import { InstalledPackages } from './installed-packages';
|
import { InstalledPackages } from './installed-packages';
|
||||||
import { InvalidAuthToken } from './invalid-auth-token';
|
import { InvalidAuthToken } from './invalid-auth-token';
|
||||||
|
@ -66,4 +67,5 @@ export const entities = {
|
||||||
TestMetric,
|
TestMetric,
|
||||||
TestRun,
|
TestRun,
|
||||||
TestCaseExecution,
|
TestCaseExecution,
|
||||||
|
Folder,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
import { Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, OneToMany } from '@n8n/typeorm';
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
JoinColumn,
|
||||||
|
JoinTable,
|
||||||
|
ManyToMany,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
} from '@n8n/typeorm';
|
||||||
import { Length } from 'class-validator';
|
import { Length } from 'class-validator';
|
||||||
import { IConnections, IDataObject, IWorkflowSettings, WorkflowFEMeta } from 'n8n-workflow';
|
import { IConnections, IDataObject, IWorkflowSettings, WorkflowFEMeta } from 'n8n-workflow';
|
||||||
import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
|
import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
|
||||||
|
@ -6,6 +15,7 @@ import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
|
||||||
import type { IWorkflowDb } from '@/interfaces';
|
import type { IWorkflowDb } from '@/interfaces';
|
||||||
|
|
||||||
import { WithTimestampsAndStringId, dbType, jsonColumnType } from './abstract-entity';
|
import { WithTimestampsAndStringId, dbType, jsonColumnType } from './abstract-entity';
|
||||||
|
import { type Folder } from './folder';
|
||||||
import type { SharedWorkflow } from './shared-workflow';
|
import type { SharedWorkflow } from './shared-workflow';
|
||||||
import type { TagEntity } from './tag-entity';
|
import type { TagEntity } from './tag-entity';
|
||||||
import type { WorkflowStatistics } from './workflow-statistics';
|
import type { WorkflowStatistics } from './workflow-statistics';
|
||||||
|
@ -88,6 +98,13 @@ export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkfl
|
||||||
@Column({ default: 0 })
|
@Column({ default: 0 })
|
||||||
triggerCount: number;
|
triggerCount: number;
|
||||||
|
|
||||||
|
@ManyToOne('Folder', 'workflows', {
|
||||||
|
nullable: true,
|
||||||
|
onDelete: 'SET NULL',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'parentFolderId' })
|
||||||
|
parentFolder: Folder | null;
|
||||||
|
|
||||||
display() {
|
display() {
|
||||||
return `"${this.name}" (ID: ${this.id})`;
|
return `"${this.name}" (ID: ${this.id})`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
|
||||||
|
|
||||||
|
export class CreateFolderTable1738709609940 implements ReversibleMigration {
|
||||||
|
async up({ runQuery, escape, schemaBuilder: { createTable, column } }: MigrationContext) {
|
||||||
|
const workflowTable = escape.tableName('workflow_entity');
|
||||||
|
const workflowFolderId = escape.columnName('parentFolderId');
|
||||||
|
const folderTable = escape.tableName('folder');
|
||||||
|
const folderId = escape.columnName('id');
|
||||||
|
|
||||||
|
await createTable('folder')
|
||||||
|
.withColumns(
|
||||||
|
column('id').varchar(36).primary.notNull,
|
||||||
|
column('name').varchar(128).notNull,
|
||||||
|
column('parentFolderId').varchar(36).default(null),
|
||||||
|
column('projectId').varchar(36).notNull,
|
||||||
|
)
|
||||||
|
.withForeignKey('projectId', {
|
||||||
|
tableName: 'project',
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
.withForeignKey('parentFolderId', {
|
||||||
|
tableName: 'folder',
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
.withIndexOn(['projectId', 'id'], true).withTimestamps;
|
||||||
|
|
||||||
|
await createTable('folder_tag')
|
||||||
|
.withColumns(
|
||||||
|
column('folderId').varchar(36).primary.notNull,
|
||||||
|
column('tagId').varchar(36).primary.notNull,
|
||||||
|
)
|
||||||
|
.withForeignKey('folderId', {
|
||||||
|
tableName: 'folder',
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
.withForeignKey('tagId', {
|
||||||
|
tableName: 'tag_entity',
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
});
|
||||||
|
|
||||||
|
await runQuery(
|
||||||
|
`ALTER TABLE ${workflowTable} ADD COLUMN ${workflowFolderId} VARCHAR(36) DEFAULT NULL REFERENCES ${folderTable}(${folderId}) ON DELETE SET NULL`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down({ runQuery, escape, schemaBuilder: { dropTable } }: MigrationContext) {
|
||||||
|
const workflowTable = escape.tableName('workflow_entity');
|
||||||
|
const workflowFolderId = escape.columnName('parentFolderId');
|
||||||
|
|
||||||
|
await runQuery(`ALTER TABLE ${workflowTable} DROP COLUMN ${workflowFolderId}`);
|
||||||
|
|
||||||
|
await dropTable('folder_tag');
|
||||||
|
|
||||||
|
await dropTable('folder');
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,6 +79,7 @@ import { AddManagedColumnToCredentialsTable1734479635324 } from '../common/17344
|
||||||
import { AddStatsColumnsToTestRun1736172058779 } from '../common/1736172058779-AddStatsColumnsToTestRun';
|
import { AddStatsColumnsToTestRun1736172058779 } from '../common/1736172058779-AddStatsColumnsToTestRun';
|
||||||
import { CreateTestCaseExecutionTable1736947513045 } from '../common/1736947513045-CreateTestCaseExecutionTable';
|
import { CreateTestCaseExecutionTable1736947513045 } from '../common/1736947513045-CreateTestCaseExecutionTable';
|
||||||
import { AddErrorColumnsToTestRuns1737715421462 } from '../common/1737715421462-AddErrorColumnsToTestRuns';
|
import { AddErrorColumnsToTestRuns1737715421462 } from '../common/1737715421462-AddErrorColumnsToTestRuns';
|
||||||
|
import { CreateFolderTable1738709609940 } from '../common/1738709609940-CreateFolderTable';
|
||||||
|
|
||||||
export const mysqlMigrations: Migration[] = [
|
export const mysqlMigrations: Migration[] = [
|
||||||
InitialMigration1588157391238,
|
InitialMigration1588157391238,
|
||||||
|
@ -160,4 +161,5 @@ export const mysqlMigrations: Migration[] = [
|
||||||
AddStatsColumnsToTestRun1736172058779,
|
AddStatsColumnsToTestRun1736172058779,
|
||||||
CreateTestCaseExecutionTable1736947513045,
|
CreateTestCaseExecutionTable1736947513045,
|
||||||
AddErrorColumnsToTestRuns1737715421462,
|
AddErrorColumnsToTestRuns1737715421462,
|
||||||
|
CreateFolderTable1738709609940,
|
||||||
];
|
];
|
||||||
|
|
|
@ -79,6 +79,7 @@ import { AddManagedColumnToCredentialsTable1734479635324 } from '../common/17344
|
||||||
import { AddStatsColumnsToTestRun1736172058779 } from '../common/1736172058779-AddStatsColumnsToTestRun';
|
import { AddStatsColumnsToTestRun1736172058779 } from '../common/1736172058779-AddStatsColumnsToTestRun';
|
||||||
import { CreateTestCaseExecutionTable1736947513045 } from '../common/1736947513045-CreateTestCaseExecutionTable';
|
import { CreateTestCaseExecutionTable1736947513045 } from '../common/1736947513045-CreateTestCaseExecutionTable';
|
||||||
import { AddErrorColumnsToTestRuns1737715421462 } from '../common/1737715421462-AddErrorColumnsToTestRuns';
|
import { AddErrorColumnsToTestRuns1737715421462 } from '../common/1737715421462-AddErrorColumnsToTestRuns';
|
||||||
|
import { CreateFolderTable1738709609940 } from '../common/1738709609940-CreateFolderTable';
|
||||||
|
|
||||||
export const postgresMigrations: Migration[] = [
|
export const postgresMigrations: Migration[] = [
|
||||||
InitialMigration1587669153312,
|
InitialMigration1587669153312,
|
||||||
|
@ -160,4 +161,5 @@ export const postgresMigrations: Migration[] = [
|
||||||
AddStatsColumnsToTestRun1736172058779,
|
AddStatsColumnsToTestRun1736172058779,
|
||||||
CreateTestCaseExecutionTable1736947513045,
|
CreateTestCaseExecutionTable1736947513045,
|
||||||
AddErrorColumnsToTestRuns1737715421462,
|
AddErrorColumnsToTestRuns1737715421462,
|
||||||
|
CreateFolderTable1738709609940,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { CreateFolderTable1738709609940 as BaseMigration } from '../common/1738709609940-CreateFolderTable';
|
||||||
|
|
||||||
|
export class CreateFolderTable1738709609940 extends BaseMigration {
|
||||||
|
transaction = false as const;
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ import { AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644 } from './17286
|
||||||
import { AddProjectIcons1729607673469 } from './1729607673469-AddProjectIcons';
|
import { AddProjectIcons1729607673469 } from './1729607673469-AddProjectIcons';
|
||||||
import { AddDescriptionToTestDefinition1731404028106 } from './1731404028106-AddDescriptionToTestDefinition';
|
import { AddDescriptionToTestDefinition1731404028106 } from './1731404028106-AddDescriptionToTestDefinition';
|
||||||
import { MigrateTestDefinitionKeyToString1731582748663 } from './1731582748663-MigrateTestDefinitionKeyToString';
|
import { MigrateTestDefinitionKeyToString1731582748663 } from './1731582748663-MigrateTestDefinitionKeyToString';
|
||||||
|
import { CreateFolderTable1738709609940 } from './1738709609940-CreateFolderTable';
|
||||||
import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames';
|
import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames';
|
||||||
import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials';
|
import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials';
|
||||||
import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds';
|
import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds';
|
||||||
|
@ -154,6 +155,7 @@ const sqliteMigrations: Migration[] = [
|
||||||
AddStatsColumnsToTestRun1736172058779,
|
AddStatsColumnsToTestRun1736172058779,
|
||||||
CreateTestCaseExecutionTable1736947513045,
|
CreateTestCaseExecutionTable1736947513045,
|
||||||
AddErrorColumnsToTestRuns1737715421462,
|
AddErrorColumnsToTestRuns1737715421462,
|
||||||
|
CreateFolderTable1738709609940,
|
||||||
];
|
];
|
||||||
|
|
||||||
export { sqliteMigrations };
|
export { sqliteMigrations };
|
||||||
|
|
11
packages/cli/src/databases/repositories/folder.repository.ts
Normal file
11
packages/cli/src/databases/repositories/folder.repository.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { Service } from '@n8n/di';
|
||||||
|
import { DataSource, Repository } from '@n8n/typeorm';
|
||||||
|
|
||||||
|
import { Folder } from '../entities/folder';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class FolderRepository extends Repository<Folder> {
|
||||||
|
constructor(dataSource: DataSource) {
|
||||||
|
super(Folder, dataSource.manager);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue