mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-31 16:57:08 +02:00
enforce constraint and offer shared accessor
This commit is contained in:
parent
5cd64171f1
commit
bab2f0728b
|
|
@ -1,14 +1,15 @@
|
|||
import {
|
||||
BeforeInsert,
|
||||
BeforeUpdate,
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
JoinTable,
|
||||
ManyToOne,
|
||||
OneToOne,
|
||||
PrimaryColumn,
|
||||
Relation,
|
||||
} from '@n8n/typeorm';
|
||||
import { IWorkflowBase } from 'n8n-workflow';
|
||||
import { IWorkflowBase, UnexpectedError } from 'n8n-workflow';
|
||||
|
||||
import { JsonColumn } from './abstract-entity';
|
||||
import { ExecutionEntity } from './execution-entity';
|
||||
|
|
@ -16,6 +17,8 @@ import { ISimplifiedPinData } from './types-db';
|
|||
import { WorkflowHistory } from './workflow-history';
|
||||
import { idStringifier } from '../utils/transformers';
|
||||
|
||||
type WorkflowData = Omit<IWorkflowBase, 'pinData'> & { pinData?: ISimplifiedPinData };
|
||||
|
||||
@Entity()
|
||||
export class ExecutionData {
|
||||
@Column('text')
|
||||
|
|
@ -31,20 +34,38 @@ export class ExecutionData {
|
|||
* due to `INodeExecutionData`, so we use a simplified version so `QueryDeepPartialEntity`
|
||||
* can resolve and calls to `update`, `insert`, and `insert` pass typechecking.
|
||||
*/
|
||||
@JsonColumn()
|
||||
workflowData: Omit<IWorkflowBase, 'pinData'> & { pinData?: ISimplifiedPinData };
|
||||
@JsonColumn({ nullable: true })
|
||||
workflowData: WorkflowData | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 36, nullable: true })
|
||||
workflowVersionId: string | null;
|
||||
|
||||
@ManyToOne(() => WorkflowHistory, { onDelete: 'SET NULL', nullable: true })
|
||||
@JoinTable({
|
||||
joinColumn: {
|
||||
name: 'workflowVersionId',
|
||||
referencedColumnName: 'versionId',
|
||||
},
|
||||
@JoinColumn({
|
||||
name: 'workflowVersionId',
|
||||
referencedColumnName: 'versionId',
|
||||
})
|
||||
workflowHistory?: Relation<WorkflowHistory> | null;
|
||||
workflowHistory: Relation<WorkflowHistory> | null;
|
||||
|
||||
@BeforeInsert()
|
||||
@BeforeUpdate()
|
||||
validateRelations() {
|
||||
if (this.workflowData === null && this.workflowVersionId === null) {
|
||||
throw new Error('Either workflowData or workflowVersionId must be provided');
|
||||
}
|
||||
}
|
||||
|
||||
get workflow(): WorkflowData {
|
||||
if (this.workflowData) {
|
||||
return this.workflowData;
|
||||
}
|
||||
|
||||
if (this.workflowHistory === null) {
|
||||
throw new UnexpectedError('ExecutionData invariant broken');
|
||||
}
|
||||
|
||||
return { ...this.workflowHistory.workflow, ...this.workflowHistory };
|
||||
}
|
||||
|
||||
@PrimaryColumn({ transformer: idStringifier })
|
||||
executionId: string;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export class WorkflowHistory extends WithTimestamps {
|
|||
@Column()
|
||||
authors: string;
|
||||
|
||||
@ManyToOne('WorkflowEntity', {
|
||||
@ManyToOne(() => WorkflowEntity, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
workflow: Relation<WorkflowEntity>;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ import { Service } from '@n8n/di';
|
|||
import { DataSource, In, Repository } from '@n8n/typeorm';
|
||||
import type { EntityManager } from '@n8n/typeorm';
|
||||
import type { QueryDeepPartialEntity } from '@n8n/typeorm/query-builder/QueryPartialEntity';
|
||||
import { IWorkflowBase } from 'n8n-workflow';
|
||||
|
||||
import { ISimplifiedPinData } from 'entities/types-db';
|
||||
|
||||
import { ExecutionData } from '../entities';
|
||||
import { IWorkflowBase } from 'n8n-workflow';
|
||||
import { ISimplifiedPinData } from 'entities/types-db';
|
||||
|
||||
@Service()
|
||||
export class ExecutionDataRepository extends Repository<ExecutionData> {
|
||||
|
|
@ -32,10 +33,6 @@ export class ExecutionDataRepository extends Repository<ExecutionData> {
|
|||
where: {
|
||||
executionId: In(executionIds),
|
||||
},
|
||||
}).then((executionData) =>
|
||||
executionData.map(({ workflowData, workflowHistory }) =>
|
||||
workflowHistory ? { ...workflowHistory.workflow, ...workflowHistory } : workflowData,
|
||||
),
|
||||
);
|
||||
}).then((executionData) => executionData.map(({ workflow }) => workflow));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
|||
this.errorReporter.error('Found successful execution where data is empty stringified array', {
|
||||
extra: {
|
||||
executionId: execution.id,
|
||||
workflowId: executionData?.workflowData.id,
|
||||
workflowId: executionData?.workflow.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export class ChatHubMessage extends WithTimestamps {
|
|||
() => ChatHubMessage,
|
||||
(m: ChatHubMessage) => m.previousMessage,
|
||||
)
|
||||
responses?: Array<Relation<ChatHubMessage>>;
|
||||
responses?: Relation<ChatHubMessage[]>;
|
||||
|
||||
/**
|
||||
* ID of the message that this message is a retry of (if applicable).
|
||||
|
|
@ -156,7 +156,7 @@ export class ChatHubMessage extends WithTimestamps {
|
|||
() => ChatHubMessage,
|
||||
(m: ChatHubMessage) => m.retryOfMessage,
|
||||
)
|
||||
retries?: Array<Relation<ChatHubMessage>>;
|
||||
retries?: Relation<ChatHubMessage[]>;
|
||||
|
||||
/**
|
||||
* ID of the message that this message is a revision/edit of (if applicable).
|
||||
|
|
@ -185,7 +185,7 @@ export class ChatHubMessage extends WithTimestamps {
|
|||
() => ChatHubMessage,
|
||||
(m: ChatHubMessage) => m.revisionOfMessage,
|
||||
)
|
||||
revisions?: Array<Relation<ChatHubMessage>>;
|
||||
revisions?: Relation<ChatHubMessage[]>;
|
||||
|
||||
/**
|
||||
* Status of the message, e.g. 'running', 'success', 'error', 'cancelled'.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
PrimaryGeneratedColumn,
|
||||
} from '@n8n/typeorm';
|
||||
|
||||
import type { ChatHubMessage } from './chat-hub-message.entity';
|
||||
import { ChatHubMessage } from './chat-hub-message.entity';
|
||||
|
||||
@Entity({ name: 'chat_hub_sessions' })
|
||||
export class ChatHubSession extends WithTimestamps {
|
||||
|
|
@ -33,7 +33,7 @@ export class ChatHubSession extends WithTimestamps {
|
|||
/**
|
||||
* The user that owns this chat session.
|
||||
*/
|
||||
@ManyToOne('User', { onDelete: 'CASCADE' })
|
||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'ownerId' })
|
||||
owner?: Relation<User>;
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ export class ChatHubSession extends WithTimestamps {
|
|||
/**
|
||||
* The selected credential to use by default with the selected LLM provider (if applicable).
|
||||
*/
|
||||
@ManyToOne('CredentialsEntity', { onDelete: 'SET NULL', nullable: true })
|
||||
@ManyToOne(() => CredentialsEntity, { onDelete: 'SET NULL', nullable: true })
|
||||
@JoinColumn({ name: 'credentialId' })
|
||||
credential?: Relation<CredentialsEntity> | null;
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ export class ChatHubSession extends WithTimestamps {
|
|||
/**
|
||||
* Custom n8n agent workflow to use (if applicable)
|
||||
*/
|
||||
@ManyToOne('WorkflowEntity', { onDelete: 'SET NULL', nullable: true })
|
||||
@ManyToOne(() => WorkflowEntity, { onDelete: 'SET NULL', nullable: true })
|
||||
@JoinColumn({ name: 'workflowId' })
|
||||
workflow?: Relation<WorkflowEntity> | null;
|
||||
|
||||
|
|
@ -100,6 +100,6 @@ export class ChatHubSession extends WithTimestamps {
|
|||
/**
|
||||
* All messages that belong to this chat session.
|
||||
*/
|
||||
@OneToMany('ChatHubMessage', 'session')
|
||||
messages?: Array<Relation<ChatHubMessage>>;
|
||||
@OneToMany(() => ChatHubMessage, 'session')
|
||||
messages?: Relation<ChatHubMessage[]>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user