feat(core): Expose data store service to Data Store Node (no-changelog) (#17970)

Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
This commit is contained in:
Charlie Kolb
2025-08-19 17:43:19 +02:00
committed by GitHub
parent 970351bf23
commit 169acd12bd
20 changed files with 547 additions and 15 deletions

View File

@@ -0,0 +1,106 @@
export type DataStoreColumnType = 'string' | 'number' | 'boolean' | 'date';
export type DataStoreColumn = {
id: string;
name: string;
type: DataStoreColumnType;
index: number;
dataStoreId: string;
};
export type DataStore = {
id: string;
name: string;
columns: DataStoreColumn[];
createdAt: Date;
updatedAt: Date;
projectId: string;
sizeBytes: number;
};
export type CreateDataStoreColumnOptions = Pick<DataStoreColumn, 'name' | 'type'> &
Partial<Pick<DataStoreColumn, 'index'>>;
export type CreateDataStoreOptions = Pick<DataStore, 'name'> & {
columns: CreateDataStoreColumnOptions[];
};
export type UpdateDataStoreOptions = { name: string };
export type ListDataStoreOptions = {
filter?: Record<string, string | string[]>;
sortBy?:
| 'name:asc'
| 'name:desc'
| 'createdAt:asc'
| 'createdAt:desc'
| 'updatedAt:asc'
| 'updatedAt:desc'
| 'sizeBytes:asc'
| 'sizeBytes:desc';
take?: number;
skip?: number;
};
export type ListDataStoreContentFilter = {
type: 'and' | 'or';
filters: Array<{
columnName: string;
condition: 'eq' | 'neq';
value: string | number | boolean | Date;
}>;
};
export type ListDataStoreRowsOptions = {
filter?: ListDataStoreContentFilter;
sortBy?: [string, 'ASC' | 'DESC'];
take?: number;
skip?: number;
};
export type UpsertDataStoreRowsOptions = {
rows: DataStoreRows;
matchFields: string[];
};
export type MoveDataStoreColumnOptions = {
targetIndex: number;
};
export type AddDataStoreColumnOptions = Pick<DataStoreColumn, 'name' | 'type'> &
Partial<Pick<DataStoreColumn, 'index'>>;
export type DataStoreColumnJsType = string | number | boolean | Date;
export type DataStoreRows = Array<Record<string, DataStoreColumnJsType | null>>;
// APIs for a data store service operating on a specific projectId
export interface IDataStoreProjectAggregateService {
createDataStore(options: CreateDataStoreOptions): Promise<DataStore>;
getManyAndCount(options: ListDataStoreOptions): Promise<{ count: number; data: DataStore[] }>;
deleteDataStoreAll(): Promise<boolean>;
}
// APIs for a data store service operating on a specific projectId and dataStoreId
export interface IDataStoreProjectService {
updateDataStore(options: UpdateDataStoreOptions): Promise<boolean>;
deleteDataStore(): Promise<boolean>;
getColumns(): Promise<DataStoreColumn[]>;
addColumn(options: AddDataStoreColumnOptions): Promise<DataStoreColumn>;
moveColumn(columnId: string, options: MoveDataStoreColumnOptions): Promise<boolean>;
deleteColumn(columnId: string): Promise<boolean>;
getManyRowsAndCount(
dto: Partial<ListDataStoreRowsOptions>,
): Promise<{ count: number; data: DataStoreRows }>;
insertRows(rows: DataStoreRows): Promise<boolean>;
upsertRows(options: UpsertDataStoreRowsOptions): Promise<boolean>;
}

View File

@@ -7,6 +7,7 @@ export * from './errors';
export * from './constants';
export * from './common';
export * from './cron';
export * from './data-store.types';
export * from './deferred-promise';
export * from './global-state';
export * from './interfaces';

View File

@@ -13,6 +13,10 @@ import type { SecureContextOptions } from 'tls';
import type { URLSearchParams } from 'url';
import type { CODE_EXECUTION_MODES, CODE_LANGUAGES, LOG_LEVELS } from './constants';
import type {
IDataStoreProjectAggregateService,
IDataStoreProjectService,
} from './data-store.types';
import type { IDeferredPromise } from './deferred-promise';
import type { ExecutionCancelledError } from './errors';
import type { ExpressionError } from './errors/expression.error';
@@ -916,6 +920,24 @@ type FunctionsBaseWithRequiredKeys<Keys extends keyof FunctionsBase> = Functions
export type ContextType = 'flow' | 'node';
export type DataStoreProxyProvider = {
getDataStoreAggregateProxy(
workflow: Workflow,
node: INode,
): Promise<IDataStoreProjectAggregateService>;
getDataStoreProxy(
workflow: Workflow,
node: INode,
dataStoreId: string,
): Promise<IDataStoreProjectService>;
};
export type DataStoreProxyFunctions = {
// These are optional to account for situations where the data-store module is disabled
getDataStoreAggregateProxy?(): Promise<IDataStoreProjectAggregateService>;
getDataStoreProxy?(dataStoreId: string): Promise<IDataStoreProjectService>;
};
type BaseExecutionFunctions = FunctionsBaseWithRequiredKeys<'getMode'> & {
continueOnFail(): boolean;
setMetadata(metadata: ITaskMetadata): void;
@@ -978,7 +1000,8 @@ export type IExecuteFunctions = ExecuteFunctions.GetNodeParameterFn &
BinaryHelperFunctions &
DeduplicationHelperFunctions &
FileSystemHelperFunctions &
SSHTunnelFunctions & {
SSHTunnelFunctions &
DataStoreProxyFunctions & {
normalizeItems(items: INodeExecutionData | INodeExecutionData[]): INodeExecutionData[];
constructExecutionMetaData(
inputData: INodeExecutionData[],
@@ -1062,7 +1085,7 @@ export interface ILoadOptionsFunctions extends FunctionsBase {
): NodeParameterValueType | object | undefined;
getCurrentNodeParameters(): INodeParameters | undefined;
helpers: RequestHelperFunctions & SSHTunnelFunctions;
helpers: RequestHelperFunctions & SSHTunnelFunctions & DataStoreProxyFunctions;
}
export type FieldValueOption = { name: string; type: FieldType | 'any' };