Move it all experiment

This commit is contained in:
Iván Ovejero 2025-04-24 10:57:00 +02:00
parent eba881a1d3
commit 44c8ea472e
No known key found for this signature in database
621 changed files with 2336 additions and 2058 deletions

View File

@ -21,14 +21,15 @@
"dist/**/*"
],
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@n8n/config": "workspace:*"
"@n8n/config": "workspace:*",
"@n8n/typescript-config": "workspace:*"
},
"dependencies": {
"@n8n/constants": "workspace:^",
"@n8n/permissions": "workspace:*",
"n8n-workflow": "workspace:*",
"xss": "catalog:",
"zod": "catalog:",
"zod-class": "0.0.16",
"@n8n/permissions": "workspace:*"
"zod-class": "0.0.16"
}
}

View File

@ -0,0 +1,60 @@
import type { ExecutionStatus } from '@n8n/constants';
import type { Scope } from '@n8n/permissions';
import type { ExecutionSummary } from 'n8n-workflow';
export type AnnotationVote = 'up' | 'down';
export type ListQueryOptions = {
filter?: Record<string, unknown>;
select?: Record<string, true>;
skip?: number;
take?: number;
sortBy?: string;
};
export type Query = RangeQuery | CountQuery;
export type RangeQuery = { kind: 'range' } & FilterFields &
AccessFields &
RangeFields &
OrderFields;
export type CountQuery = { kind: 'count' } & FilterFields & AccessFields;
type FilterFields = Partial<{
id: string;
finished: boolean;
mode: string;
retryOf: string;
retrySuccessId: string;
status: ExecutionStatus[];
workflowId: string;
waitTill: boolean;
metadata: Array<{ key: string; value: string }>;
startedAfter: string;
startedBefore: string;
annotationTags: string[]; // tag IDs
vote: AnnotationVote;
projectId: string;
}>;
type AccessFields = {
accessibleWorkflowIds?: string[];
};
type RangeFields = {
range: {
limit: number;
firstId?: string;
lastId?: string;
};
};
type OrderFields = {
order?: {
top?: ExecutionStatus;
startedAt?: 'DESC';
};
};
export type ExecutionSummaryWithScopes = ExecutionSummary & { scopes: Scope[] };

View File

@ -0,0 +1,41 @@
import type { ExecutionStatus } from '@n8n/constants';
import type { WorkflowExecuteMode, IRunExecutionData, IWorkflowBase } from 'n8n-workflow';
// Data in regular format with references
export interface IExecutionDb extends IExecutionBase {
data: IRunExecutionData;
workflowData: IWorkflowBase;
}
/** Payload for creating an execution. */
export type CreateExecutionPayload = Omit<IExecutionDb, 'id' | 'createdAt' | 'startedAt'>;
export interface IExecutionBase {
id: string;
mode: WorkflowExecuteMode;
createdAt: Date; // set by DB
startedAt: Date;
stoppedAt?: Date; // empty value means execution is still running
workflowId: string;
/**
* @deprecated Use `status` instead
*/
finished: boolean;
retryOf?: string; // If it is a retry, the id of the execution it is a retry of.
retrySuccessId?: string; // If it failed and a retry did succeed. The id of the successful retry.
status: ExecutionStatus;
waitTill?: Date | null;
}
export interface IExecutionFlattedDb extends IExecutionBase {
id: string;
data: string;
workflowData: Omit<IWorkflowBase, 'pinData'>;
customData: Record<string, string>;
}
export interface ITagBase {
id: string;
name: string;
}

View File

@ -36,3 +36,18 @@ export type {
InsightsByWorkflow,
InsightsByTime,
} from './schemas/insights.schema';
export {
ListQueryOptions,
Query,
CountQuery,
RangeQuery,
ExecutionSummaryWithScopes,
} from './execution-summaries';
export {
ITagBase,
IExecutionBase,
IExecutionFlattedDb,
CreateExecutionPayload,
IExecutionDb,
} from './execution';

View File

@ -20,5 +20,8 @@
],
"devDependencies": {
"@n8n/typescript-config": "workspace:*"
},
"dependencies": {
"@n8n/permissions": "workspace:^"
}
}

View File

@ -45,3 +45,72 @@ export const UNLIMITED_LICENSE_QUOTA = -1;
export type BooleanLicenseFeature = (typeof LICENSE_FEATURES)[keyof typeof LICENSE_FEATURES];
export type NumericLicenseFeature = (typeof LICENSE_QUOTAS)[keyof typeof LICENSE_QUOTAS];
const { NODE_ENV } = process.env;
export const inTest = NODE_ENV === 'test';
export { GLOBAL_OWNER_SCOPES, GLOBAL_ADMIN_SCOPES, GLOBAL_MEMBER_SCOPES } from './global-roles';
export const ExecutionStatusList = [
'canceled',
'crashed',
'error',
'new',
'running',
'success',
'unknown',
'waiting',
] as const;
export type ExecutionStatus = (typeof ExecutionStatusList)[number];
export const EXTERNAL_SECRETS_DB_KEY = 'feature.externalSecrets';
export type ConnectionSecurity = 'none' | 'tls' | 'startTls';
export interface LdapConfig {
loginEnabled: boolean;
loginLabel: string;
connectionUrl: string;
allowUnauthorizedCerts: boolean;
connectionSecurity: ConnectionSecurity;
connectionPort: number;
baseDn: string;
bindingAdminDn: string;
bindingAdminPassword: string;
firstNameAttribute: string;
lastNameAttribute: string;
emailAttribute: string;
loginIdAttribute: string;
ldapIdAttribute: string;
userFilter: string;
synchronizationEnabled: boolean;
synchronizationInterval: number; // minutes
searchPageSize: number;
searchTimeout: number;
}
export const LDAP_DEFAULT_CONFIGURATION: LdapConfig = {
loginEnabled: false,
loginLabel: '',
connectionUrl: '',
allowUnauthorizedCerts: false,
connectionSecurity: 'none',
connectionPort: 389,
baseDn: '',
bindingAdminDn: '',
bindingAdminPassword: '',
firstNameAttribute: '',
lastNameAttribute: '',
emailAttribute: '',
loginIdAttribute: '',
ldapIdAttribute: '',
userFilter: '',
synchronizationEnabled: false,
synchronizationInterval: 60,
searchPageSize: 0,
searchTimeout: 60,
};
export const LDAP_FEATURE_NAME = 'features.ldap';

View File

@ -1,52 +0,0 @@
## @n8n/di
`@n8n/di` is a dependency injection (DI) container library, based on [`typedi`](https://github.com/typestack/typedi).
n8n no longer uses `typedi` because:
- `typedi` is no longer officially maintained
- Need for future-proofing, e.g. stage-3 decorators
- Small enough that it is worth the maintenance burden
- Easier to customize, e.g. to simplify unit tests
### Usage
```typescript
// from https://github.com/typestack/typedi/blob/develop/README.md
import { Container, Service } from 'typedi';
@Service()
class ExampleInjectedService {
printMessage() {
console.log('I am alive!');
}
}
@Service()
class ExampleService {
constructor(
// because we annotated ExampleInjectedService with the @Service()
// decorator TypeDI will automatically inject an instance of
// ExampleInjectedService here when the ExampleService class is requested
// from TypeDI.
public injectedService: ExampleInjectedService
) {}
}
const serviceInstance = Container.get(ExampleService);
// we request an instance of ExampleService from TypeDI
serviceInstance.injectedService.printMessage();
// logs "I am alive!" to the console
```
Requires enabling these flags in `tsconfig.json`:
```json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
```

View File

@ -21,7 +21,22 @@
"dist/**/*"
],
"dependencies": {
"reflect-metadata": "catalog:"
"@n8n/api-types": "workspace:^",
"@n8n/config": "workspace:^",
"@n8n/constants": "workspace:^",
"@n8n/di": "workspace:^",
"@n8n/permissions": "workspace:^",
"@n8n/typeorm": "0.3.20-12",
"class-validator": "0.14.0",
"flatted": "catalog:",
"lodash": "catalog:",
"n8n-core": "workspace:^",
"n8n-workflow": "workspace:^",
"nanoid": "catalog:",
"p-lazy": "3.1.0",
"reflect-metadata": "catalog:",
"uuid": "catalog:",
"xss": "catalog:"
},
"devDependencies": {
"@n8n/typescript-config": "workspace:*"

View File

@ -1,4 +1,4 @@
import { User } from '@/databases/entities/user';
import { User } from '../user';
describe('User Entity', () => {
describe('JSON.stringify', () => {

View File

@ -30,6 +30,7 @@ const tsColumnOptions: ColumnOptions = {
type: datetimeColumnType,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mixinStringId<T extends Class<{}, any[]>>(base: T) {
class Derived extends base {
@PrimaryColumn('varchar')
@ -45,6 +46,7 @@ function mixinStringId<T extends Class<{}, any[]>>(base: T) {
return Derived;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mixinTimestamps<T extends Class<{}, any[]>>(base: T) {
class Derived extends base {
@CreateDateColumn(tsColumnOptions)

View File

@ -1,10 +1,9 @@
import { Column, Entity, Index, ManyToMany, OneToMany } from '@n8n/typeorm';
import { IsString, Length } from 'class-validator';
import type { AnnotationTagMapping } from '@/databases/entities/annotation-tag-mapping.ee';
import type { ExecutionAnnotation } from '@/databases/entities/execution-annotation.ee';
import { WithTimestampsAndStringId } from './abstract-entity';
import type { AnnotationTagMapping } from './annotation-tag-mapping.ee';
import type { ExecutionAnnotation } from './execution-annotation.ee';
@Entity()
export class AnnotationTagEntity extends WithTimestampsAndStringId {

View File

@ -2,8 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryColumn, Unique } from '@n8n/typeorm';
import { WithTimestamps } from './abstract-entity';
import { User } from './user';
export type AuthProviderType = 'ldap' | 'email' | 'saml'; // | 'google';
import { AuthProviderType } from '../types';
@Entity()
@Unique(['providerId', 'providerType'])

View File

@ -1,10 +1,7 @@
import { Column, Entity, PrimaryGeneratedColumn } from '@n8n/typeorm';
import { datetimeColumnType } from './abstract-entity';
import { AuthProviderType } from './auth-identity';
export type RunningMode = 'dry' | 'live';
export type SyncStatus = 'success' | 'error';
import { RunningMode, SyncStatus, AuthProviderType } from '../types';
@Entity()
export class AuthProviderSyncHistory {

View File

@ -1,10 +1,9 @@
import { Column, Entity, Index, OneToMany } from '@n8n/typeorm';
import { IsObject, IsString, Length } from 'class-validator';
import type { ICredentialsDb } from '@/interfaces';
import { WithTimestampsAndStringId } from './abstract-entity';
import type { SharedCredentials } from './shared-credentials';
import type { ICredentialsDb } from '../types';
@Entity()
export class CredentialsEntity extends WithTimestampsAndStringId implements ICredentialsDb {

View File

@ -1,3 +1,4 @@
import { ExecutionStatus } from '@n8n/constants';
import {
Column,
Entity,
@ -10,11 +11,10 @@ import {
Relation,
DeleteDateColumn,
} from '@n8n/typeorm';
import { ExecutionStatus, WorkflowExecuteMode } from 'n8n-workflow';
import type { ExecutionAnnotation } from '@/databases/entities/execution-annotation.ee';
import { WorkflowExecuteMode } from 'n8n-workflow';
import { datetimeColumnType } from './abstract-entity';
import type { ExecutionAnnotation } from './execution-annotation.ee';
import type { ExecutionData } from './execution-data';
import type { ExecutionMetadata } from './execution-metadata';
import { WorkflowEntity } from './workflow-entity';

View File

@ -13,11 +13,6 @@ import { Project } from './project';
import { TagEntity } from './tag-entity';
import { type WorkflowEntity } from './workflow-entity';
export type FolderWithWorkflowAndSubFolderCount = Folder & {
workflowCount: boolean;
subFolderCount: number;
};
@Entity()
export class Folder extends WithTimestampsAndStringId {
@Column()

View File

@ -33,9 +33,6 @@ import { WorkflowEntity } from './workflow-entity';
import { WorkflowHistory } from './workflow-history';
import { WorkflowStatistics } from './workflow-statistics';
import { WorkflowTagMapping } from './workflow-tag-mapping';
import { InsightsByPeriod } from '../../modules/insights/database/entities/insights-by-period';
import { InsightsMetadata } from '../../modules/insights/database/entities/insights-metadata';
import { InsightsRaw } from '../../modules/insights/database/entities/insights-raw';
export const entities = {
AnnotationTagEntity,
@ -73,7 +70,9 @@ export const entities = {
TestCaseExecution,
Folder,
FolderTagMapping,
InsightsRaw,
InsightsMetadata,
InsightsByPeriod,
// @TODO: Find a way to register these below
// InsightsRaw,
// InsightsMetadata,
// InsightsByPeriod,
};

View File

@ -1,8 +1,7 @@
import { Column, Entity, PrimaryColumn } from '@n8n/typeorm';
import type { IProcessedDataEntries, IProcessedDataLatest } from '@/interfaces';
import { jsonColumnType, WithTimestamps } from './abstract-entity';
import type { IProcessedDataEntries, IProcessedDataLatest } from '../types';
import { objectRetriever } from '../utils/transformers';
@Entity()

View File

@ -0,0 +1,12 @@
import type { IDataObject } from 'n8n-workflow';
interface ISettingsDb {
key: string;
value: string | boolean | IDataObject | number;
loadOnStartup: boolean;
}
export declare class Settings implements ISettingsDb {
key: string;
value: string;
loadOnStartup: boolean;
}
export {};

View File

@ -3,8 +3,7 @@ import { Column, Entity, ManyToOne, PrimaryColumn } from '@n8n/typeorm';
import { WithTimestamps } from './abstract-entity';
import { CredentialsEntity } from './credentials-entity';
import { Project } from './project';
export type CredentialSharingRole = 'credential:owner' | 'credential:user';
import { CredentialSharingRole } from '../types';
@Entity()
export class SharedCredentials extends WithTimestamps {

View File

@ -3,8 +3,7 @@ import { Column, Entity, ManyToOne, PrimaryColumn } from '@n8n/typeorm';
import { WithTimestamps } from './abstract-entity';
import { Project } from './project';
import { WorkflowEntity } from './workflow-entity';
export type WorkflowSharingRole = 'workflow:owner' | 'workflow:editor';
import { WorkflowSharingRole } from '../types';
@Entity()
export class SharedWorkflow extends WithTimestamps {

View File

@ -1,14 +1,10 @@
import { Column, Entity, ManyToOne, OneToOne } from '@n8n/typeorm';
import type { IDataObject } from 'n8n-workflow';
import {
datetimeColumnType,
jsonColumnType,
WithStringId,
} from '@/databases/entities/abstract-entity';
import type { ExecutionEntity } from '@/databases/entities/execution-entity';
import { TestRun } from '@/databases/entities/test-run.ee';
import type { TestCaseExecutionErrorCode } from '@/evaluation.ee/test-runner/errors.ee';
import { datetimeColumnType, jsonColumnType, WithStringId } from './abstract-entity';
import type { ExecutionEntity } from './execution-entity';
import { TestRun } from './test-run.ee';
import type { TestCaseExecutionErrorCode } from '../errors';
export type TestCaseRunMetrics = Record<string, number | boolean>;

View File

@ -1,11 +1,10 @@
import { Column, Entity, Index, ManyToOne, OneToMany, RelationId } from '@n8n/typeorm';
import { Length } from 'class-validator';
import { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
import type { TestMetric } from '@/databases/entities/test-metric.ee';
import { WorkflowEntity } from '@/databases/entities/workflow-entity';
import { jsonColumnType, WithTimestampsAndStringId } from './abstract-entity';
import { AnnotationTagEntity } from './annotation-tag-entity.ee';
import type { TestMetric } from './test-metric.ee';
import { WorkflowEntity } from './workflow-entity';
// Entity representing a node in a workflow under test, for which data should be mocked during test execution
export type MockedNodeItem = {

View File

@ -1,8 +1,8 @@
import { Column, Entity, Index, ManyToOne } from '@n8n/typeorm';
import { Length } from 'class-validator';
import { WithTimestampsAndStringId } from '@/databases/entities/abstract-entity';
import { TestDefinition } from '@/databases/entities/test-definition.ee';
import { WithTimestampsAndStringId } from './abstract-entity';
import { TestDefinition } from './test-definition.ee';
/**
* Entity representing a Test Metric

View File

@ -1,15 +1,11 @@
import { Column, Entity, Index, ManyToOne, OneToMany, RelationId } from '@n8n/typeorm';
import type { IDataObject } from 'n8n-workflow';
import {
datetimeColumnType,
jsonColumnType,
WithTimestampsAndStringId,
} from '@/databases/entities/abstract-entity';
import type { TestCaseExecution } from '@/databases/entities/test-case-execution.ee';
import { TestDefinition } from '@/databases/entities/test-definition.ee';
import type { TestRunFinalResult } from '@/databases/repositories/test-run.repository.ee';
import type { TestRunErrorCode } from '@/evaluation.ee/test-runner/errors.ee';
import { datetimeColumnType, jsonColumnType, WithTimestampsAndStringId } from './abstract-entity';
import type { TestCaseExecution } from './test-case-execution.ee';
import { TestDefinition } from './test-definition.ee';
import type { TestRunErrorCode } from '../errors';
import type { TestRunFinalResult } from '../repositories/test-run.repository.ee';
export type TestRunStatus = 'new' | 'running' | 'completed' | 'error' | 'cancelled';

View File

@ -1,3 +1,4 @@
import { GLOBAL_OWNER_SCOPES, GLOBAL_MEMBER_SCOPES, GLOBAL_ADMIN_SCOPES } from '@n8n/constants';
import { hasScope, type ScopeOptions, type Scope, GlobalRole } from '@n8n/permissions';
import {
AfterLoad,
@ -13,22 +14,16 @@ import {
import { IsEmail, IsString, Length } from 'class-validator';
import type { IUser, IUserSettings } from 'n8n-workflow';
import type { IPersonalizationSurveyAnswers } from '@/interfaces';
import {
GLOBAL_OWNER_SCOPES,
GLOBAL_MEMBER_SCOPES,
GLOBAL_ADMIN_SCOPES,
} from '@/permissions.ee/global-roles';
import { NoUrl } from '@/validators/no-url.validator';
import { NoXss } from '@/validators/no-xss.validator';
import { WithTimestamps, jsonColumnType } from './abstract-entity';
import type { ApiKey } from './api-key';
import type { AuthIdentity } from './auth-identity';
import type { ProjectRelation } from './project-relation';
import type { SharedCredentials } from './shared-credentials';
import type { SharedWorkflow } from './shared-workflow';
import type { IPersonalizationSurveyAnswers } from '../types';
import { objectRetriever, lowerCaser } from '../utils/transformers';
import { NoUrl } from '../validators/no-url.validator';
import { NoXss } from '../validators/no-xss.validator';
const STATIC_SCOPE_MAP: Record<GlobalRole, Scope[]> = {
'global:owner': GLOBAL_OWNER_SCOPES,

View File

@ -12,14 +12,13 @@ import { Length } from 'class-validator';
import { IConnections, IDataObject, IWorkflowSettings, WorkflowFEMeta } from 'n8n-workflow';
import type { IBinaryKeyData, INode, IPairedItemData } from 'n8n-workflow';
import type { IWorkflowDb } from '@/interfaces';
import { WithTimestampsAndStringId, dbType, jsonColumnType } from './abstract-entity';
import { type Folder } from './folder';
import type { SharedWorkflow } from './shared-workflow';
import type { TagEntity } from './tag-entity';
import type { WorkflowStatistics } from './workflow-statistics';
import type { WorkflowTagMapping } from './workflow-tag-mapping';
import type { IWorkflowDb } from '../types';
import { objectRetriever, sqlite } from '../utils/transformers';
@Entity()

View File

@ -2,14 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryColumn } from '@n8n/typeorm';
import { datetimeColumnType } from './abstract-entity';
import { WorkflowEntity } from './workflow-entity';
export const enum StatisticsNames {
productionSuccess = 'production_success',
productionError = 'production_error',
manualSuccess = 'manual_success',
manualError = 'manual_error',
dataLoaded = 'data_loaded',
}
import { StatisticsNames } from '../types';
@Entity()
export class WorkflowStatistics {

View File

@ -0,0 +1,104 @@
/**
* @TODO Below to be moved to `@n8n/errors`
*/
import { BaseError, UnexpectedError } from 'n8n-workflow';
export type TestCaseExecutionErrorCode =
| 'MOCKED_NODE_DOES_NOT_EXIST'
| 'TRIGGER_NO_LONGER_EXISTS'
| 'FAILED_TO_EXECUTE_WORKFLOW'
| 'EVALUATION_WORKFLOW_DOES_NOT_EXIST'
| 'FAILED_TO_EXECUTE_EVALUATION_WORKFLOW'
| 'INVALID_METRICS'
| 'PAYLOAD_LIMIT_EXCEEDED'
| 'UNKNOWN_ERROR';
export class TestCaseExecutionError extends UnexpectedError {
readonly code: TestCaseExecutionErrorCode;
constructor(code: TestCaseExecutionErrorCode, extra: Record<string, unknown> = {}) {
super('Test Case execution failed with code ' + code, { extra });
this.code = code;
}
}
export type TestRunErrorCode =
| 'PAST_EXECUTIONS_NOT_FOUND'
| 'EVALUATION_WORKFLOW_NOT_FOUND'
| 'INTERRUPTED'
| 'UNKNOWN_ERROR';
export class TestRunError extends UnexpectedError {
readonly code: TestRunErrorCode;
constructor(code: TestRunErrorCode, extra: Record<string, unknown> = {}) {
super('Test Run failed with code ' + code, { extra });
this.code = code;
}
}
export class PostgresLiveRowsRetrievalError extends UnexpectedError {
constructor(rows: unknown) {
super('Failed to retrieve live execution rows in Postgres', { extra: { rows } });
}
}
/**
* @TODO The three errors below are duplicates
*/
/**
* Special Error which allows to return also an error code and http status code
*/
export abstract class ResponseError extends BaseError {
/**
* Creates an instance of ResponseError.
* Must be used inside a block with `ResponseHelper.send()`.
*/
constructor(
message: string,
// The HTTP status code of response
readonly httpStatusCode: number,
// The error code in the response
readonly errorCode: number = httpStatusCode,
// The error hint the response
readonly hint: string | undefined = undefined,
cause?: unknown,
) {
super(message, { cause });
this.name = 'ResponseError';
if (httpStatusCode >= 400 && httpStatusCode < 500) {
this.level = 'warning'; // client errors (4xx)
} else if (httpStatusCode >= 502 && httpStatusCode <= 504) {
this.level = 'info'; // transient errors (502, 503, 504)
} else {
this.level = 'error'; // other 5xx
}
}
}
export class NotFoundError extends ResponseError {
static isDefinedAndNotNull<T>(
value: T | undefined | null,
message: string,
hint?: string,
): asserts value is T {
if (value === undefined || value === null) {
throw new NotFoundError(message, hint);
}
}
constructor(message: string, hint: string | undefined = undefined) {
super(message, 404, 404, hint);
}
}
export class ForbiddenError extends ResponseError {
constructor(message = 'Forbidden', hint?: string) {
super(message, 403, 403, hint);
}
}

View File

@ -1 +1,111 @@
export {};
export { AnnotationTagEntity } from './entities/annotation-tag-entity.ee';
export { AnnotationTagMapping } from './entities/annotation-tag-mapping.ee';
export { ApiKey } from './entities/api-key';
export { AuthIdentity } from './entities/auth-identity';
export { AuthProviderSyncHistory } from './entities/auth-provider-sync-history';
export { AuthUser } from './entities/auth-user';
export { CredentialsEntity } from './entities/credentials-entity';
export { EventDestinations } from './entities/event-destinations';
export { ExecutionAnnotation } from './entities/execution-annotation.ee';
export { ExecutionData } from './entities/execution-data';
export { ExecutionEntity } from './entities/execution-entity';
export { ExecutionMetadata } from './entities/execution-metadata';
export { Folder } from './entities/folder';
export { FolderTagMapping } from './entities/folder-tag-mapping';
export { InstalledNodes } from './entities/installed-nodes';
export { InstalledPackages } from './entities/installed-packages';
export { InvalidAuthToken } from './entities/invalid-auth-token';
export { ProcessedData } from './entities/processed-data';
export { Project } from './entities/project';
export { ProjectRelation } from './entities/project-relation';
export { Settings } from './entities/settings';
export { SharedCredentials } from './entities/shared-credentials';
export { SharedWorkflow } from './entities/shared-workflow';
export { TagEntity } from './entities/tag-entity';
export { TestCaseExecution } from './entities/test-case-execution.ee';
export { TestDefinition } from './entities/test-definition.ee';
export { TestMetric } from './entities/test-metric.ee';
export { TestRun } from './entities/test-run.ee';
export { User } from './entities/user';
export { Variables } from './entities/variables';
export { WebhookEntity } from './entities/webhook-entity';
export { WorkflowEntity } from './entities/workflow-entity';
export { WorkflowHistory } from './entities/workflow-history';
export { WorkflowStatistics } from './entities/workflow-statistics';
export { WorkflowTagMapping } from './entities/workflow-tag-mapping';
export {
AnnotationTagMappingRepository,
AnnotationTagRepository,
ApiKeyRepository,
AuthIdentityRepository,
AuthProviderSyncHistoryRepository,
AuthUserRepository,
EventDestinationsRepository,
ExecutionAnnotationRepository,
ExecutionDataRepository,
ExecutionMetadataRepository,
ExecutionRepository,
FolderTagMappingRepository,
FolderRepository,
InstalledNodesRepository,
InstalledPackagesRepository,
InvalidAuthTokenRepository,
LicenseMetricsRepository,
ProcessedDataRepository,
ProjectRelationRepository,
ProjectRepository,
TagRepository,
TestCaseExecutionRepository,
TestDefinitionRepository,
TestMetricRepository,
TestRunRepository,
UserRepository,
VariablesRepository,
WebhookRepository,
WorkflowHistoryRepository,
WorkflowStatisticsRepository,
WorkflowTagMappingRepository,
WorkflowRepository,
} from './repositories';
export type {
WorkflowSharingRole,
CredentialSharingRole,
RunningMode,
SyncStatus,
IPersonalizationSurveyAnswers,
AuthProviderType,
ICredentialsBase,
IWorkflowDb,
WorkflowFolderUnionFull,
ListQueryWorkflow,
ListQueryCredentials,
SlimProject,
ICredentialsDb,
IExecutionResponse,
WorkflowWithSharingsAndCredentials,
WorkflowWithSharingsMetaDataAndCredentials,
IProcessedDataEntries,
IProcessedDataLatest,
Migration,
ScopesField,
ReversibleMigration,
IrreversibleMigration,
} from './types';
export { StatisticsNames } from './types'; // enum
export { datetimeColumnType } from './entities/abstract-entity';
export { getConnectionOptions } from './config';
export { wrapMigration } from 'utils/migration-helpers';
export { NoXss } from './validators/no-xss.validator';
export { NoUrl } from './validators/no-url.validator';
export { TestRunFinalResult } from './repositories/test-run.repository.ee';
export { MockedNodeItem } from './entities/test-definition.ee';
export { TestCaseExecutionError, TestRunError } from './errors';
export { generateNanoId } from './utils/generators';
export { arePostgresOptions, getOptionOverrides } from './config';

View File

@ -1,5 +1,5 @@
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { WorkflowEntity } from '../../entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class UniqueWorkflowNames1620821879465 implements ReversibleMigration {
protected indexSuffix = '943d8f922be094eb507cb9a7f9';

View File

@ -1,8 +1,8 @@
import type { IWorkflowBase } from 'n8n-workflow';
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { CredentialsEntity } from '../../entities/credentials-entity';
import type { WorkflowEntity } from '../../entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '../../types';
type Credential = Pick<CredentialsEntity, 'id' | 'name' | 'type'>;
type ExecutionWithData = { id: string; workflowData: string | IWorkflowBase };

View File

@ -1,8 +1,8 @@
import type { INode } from 'n8n-workflow';
import { v4 as uuid } from 'uuid';
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { WorkflowEntity } from '../../entities/workflow-entity';
import type { MigrationContext, ReversibleMigration } from '../../types';
type Workflow = Pick<WorkflowEntity, 'id'> & { nodes: string | INode[] };

View File

@ -1,7 +1,7 @@
import { isObjectLiteral } from 'n8n-core';
import type { IDataObject, INodeExecutionData } from 'n8n-workflow';
import type { MigrationContext, IrreversibleMigration } from '@/databases/types';
import type { MigrationContext, IrreversibleMigration } from '../../types';
type OldPinnedData = { [nodeName: string]: IDataObject[] };
type NewPinnedData = { [nodeName: string]: INodeExecutionData[] };

View File

@ -1,6 +1,6 @@
import { v4 as uuidv4 } from 'uuid';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
type Workflow = { id: number };

View File

@ -1,5 +1,5 @@
import { StatisticsNames } from '@/databases/entities/workflow-statistics';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import { StatisticsNames } from '../../types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class RemoveWorkflowDataLoadedFlag1671726148419 implements ReversibleMigration {
async up({ escape, dbType, runQuery }: MigrationContext) {

View File

@ -1,5 +1,6 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import { LDAP_DEFAULT_CONFIGURATION, LDAP_FEATURE_NAME } from '@/ldap.ee/constants';
import { LDAP_DEFAULT_CONFIGURATION, LDAP_FEATURE_NAME } from '@n8n/constants';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class CreateLdapEntities1674509946020 implements ReversibleMigration {
async up({ escape, dbType, isMysql, runQuery }: MigrationContext) {

View File

@ -1,5 +1,5 @@
import type { WorkflowEntity } from '@/databases/entities/workflow-entity';
import type { MigrationContext, IrreversibleMigration } from '@/databases/types';
import type { WorkflowEntity } from '../../entities/workflow-entity';
import type { MigrationContext, IrreversibleMigration } from '../../types';
interface Workflow {
id: number;
@ -8,7 +8,8 @@ interface Workflow {
}
export class PurgeInvalidWorkflowConnections1675940580449 implements IrreversibleMigration {
async up({ escape, parseJson, runQuery, nodeTypes }: MigrationContext) {
// @TODO: Restore NodeTypes
async up({ escape, parseJson, runQuery }: MigrationContext) {
const workflowsTable = escape.tableName('workflow_entity');
const workflows: Workflow[] = await runQuery(
`SELECT id, nodes, connections FROM ${workflowsTable}`,
@ -21,10 +22,10 @@ export class PurgeInvalidWorkflowConnections1675940580449 implements Irreversibl
const nodesThatCannotReceiveInput = nodes.reduce<string[]>((acc, node) => {
try {
const nodeType = nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
if ((nodeType.description.inputs?.length ?? []) === 0) {
acc.push(node.name);
}
// const nodeType = nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
// if ((nodeType.description.inputs?.length ?? []) === 0) {
// acc.push(node.name);
// }
} catch (error) {}
return acc;
}, []);

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class RemoveResetPasswordColumns1690000000030 implements ReversibleMigration {
async up({ schemaBuilder: { dropColumns } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddMfaColumns1690000000030 implements ReversibleMigration {
async up({ schemaBuilder: { addColumns, column } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class CreateWorkflowNameIndex1691088862123 implements ReversibleMigration {
async up({ schemaBuilder: { createIndex } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const tableName = 'workflow_history';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
/**
* Add an indexed column `deletedAt` to track soft-deleted executions.

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration {
/**

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddWorkflowMetadata1695128658538 implements ReversibleMigration {
async up({ schemaBuilder: { addColumns, column } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const tableName = 'workflow_history';

View File

@ -1,6 +1,6 @@
import { UnexpectedError } from 'n8n-workflow';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddGlobalAdminRole1700571993961 implements ReversibleMigration {
async up({ escape, runQuery }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
type Table = 'user' | 'shared_workflow' | 'shared_credentials';

View File

@ -1,4 +1,4 @@
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
import type { IrreversibleMigration, MigrationContext } from '../../types';
export class RemoveFailedExecutionStatus1711018413374 implements IrreversibleMigration {
async up({ escape, runQuery }: MigrationContext) {

View File

@ -4,7 +4,7 @@ import { jsonParse } from 'n8n-workflow';
import { readFile, writeFile, rm } from 'node:fs/promises';
import path from 'node:path';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
/**
* Move SSH key pair from file system to database, to enable SSH connections

View File

@ -1,4 +1,4 @@
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
import type { IrreversibleMigration, MigrationContext } from '../../types';
export class RemoveNodesAccess1712044305787 implements IrreversibleMigration {
async up({ schemaBuilder: { dropColumns } }: MigrationContext) {

View File

@ -2,9 +2,9 @@ import type { ProjectRole } from '@n8n/api-types';
import { UserError } from 'n8n-workflow';
import { nanoid } from 'nanoid';
import type { User } from '@/databases/entities/user';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import { generateNanoId } from '@/databases/utils/generators';
import type { User } from '../../entities/user';
import type { MigrationContext, ReversibleMigration } from '../../types';
import { generateNanoId } from '../../utils/generators';
const projectAdminRole: ProjectRole = 'project:personalOwner';

View File

@ -1,4 +1,4 @@
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
import type { IrreversibleMigration, MigrationContext } from '../../types';
export class MakeExecutionStatusNonNullable1714133768521 implements IrreversibleMigration {
async up({ escape, runQuery, schemaBuilder }: MigrationContext) {

View File

@ -1,6 +1,6 @@
import { nanoid } from 'nanoid';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddConstraintToExecutionMetadata1720101653148 implements ReversibleMigration {
async up(context: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const tableName = 'invalid_auth_token';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
/**
* Add new indices:

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const annotationsTableName = 'execution_annotations';
const annotationTagsTableName = 'annotation_tag_entity';

View File

@ -1,6 +1,6 @@
import type { ApiKey } from '@/databases/entities/api-key';
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import { generateNanoId } from '@/databases/utils/generators';
import type { ApiKey } from '../../entities/api-key';
import type { MigrationContext, ReversibleMigration } from '../../types';
import { generateNanoId } from '../../utils/generators';
export class AddApiKeysTable1724951148974 implements ReversibleMigration {
async up({
@ -39,6 +39,7 @@ export class AddApiKeysTable1724951148974 implements ReversibleMigration {
// Move the apiKey from the users table to the new table
await Promise.all(
usersWithApiKeys.map(
// @ts-expect-error Fix typing
async (user: { id: string; apiKey: string }) =>
await runQuery(
`INSERT INTO ${userApiKeysTable} (${idColumn}, ${userIdColumn}, ${apiKeyColumn}, ${labelColumn}) VALUES (:id, :userId, :apiKey, :label)`,
@ -96,6 +97,7 @@ export class AddApiKeysTable1724951148974 implements ReversibleMigration {
await Promise.all(
oldestApiKeysPerUser.map(
// @ts-expect-error Fix typing
async (user: { userId: string; apiKey: string }) =>
await runQuery(
`UPDATE ${userTable} SET ${apiKeyColumn} = :apiKey WHERE ${idColumn} = :userId`,

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const processedDataTableName = 'processed_data';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class SeparateExecutionCreationFromStart1727427440136 implements ReversibleMigration {
async up({

View File

@ -1,6 +1,6 @@
import assert from 'node:assert';
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
import type { IrreversibleMigration, MigrationContext } from '../../types';
export class AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644
implements IrreversibleMigration

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const processedDataTableName = 'processed_data';
export class UpdateProcessedDataValueColumnToText1729607673464 implements ReversibleMigration {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddProjectIcons1729607673469 implements ReversibleMigration {
async up({ schemaBuilder: { addColumns, column } }: MigrationContext) {
await addColumns('project', [column('icon').json]);

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const testEntityTableName = 'test_definition';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddDescriptionToTestDefinition1731404028106 implements ReversibleMigration {
async up({ schemaBuilder: { addColumns, column } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const testMetricEntityTableName = 'test_metric';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const testRunTableName = 'test_run';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
// We have to use raw query migration instead of schemaBuilder helpers,
// because the typeorm schema builder implements addColumns by a table recreate for sqlite

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class AddManagedColumnToCredentialsTable1734479635324 implements ReversibleMigration {
async up({ escape, runQuery, isSqlite }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const columns = ['totalCases', 'passedCases', 'failedCases'] as const;

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const testCaseExecutionTableName = 'test_case_execution';

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
// We have to use raw query migration instead of schemaBuilder helpers,
// because the typeorm schema builder implements addColumns by a table recreate for sqlite

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
export class CreateFolderTable1738709609940 implements ReversibleMigration {
async up({ runQuery, escape, schemaBuilder: { createTable, column } }: MigrationContext) {

View File

@ -1,4 +1,4 @@
import type { MigrationContext, ReversibleMigration } from '@/databases/types';
import type { MigrationContext, ReversibleMigration } from '../../types';
const names = {
// table names

View File

@ -1,4 +1,4 @@
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
import type { IrreversibleMigration, MigrationContext } from '../../types';
const names = {
// table names

Some files were not shown because too many files have changed in this diff Show More