mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-27 23:07:12 +02:00
wip commit
This commit is contained in:
parent
01900d57f3
commit
331fc9b1bd
|
|
@ -2,6 +2,4 @@ import { Z } from 'zod-class';
|
|||
|
||||
import { dataStoreCreateColumnSchema } from '../../schemas/data-store.schema';
|
||||
|
||||
export class AddDataStoreColumnDto extends Z.class({
|
||||
column: dataStoreCreateColumnSchema,
|
||||
}) {}
|
||||
export class AddDataStoreColumnDto extends Z.class(dataStoreCreateColumnSchema.shape) {}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { z } from 'zod';
|
|||
import { Z } from 'zod-class';
|
||||
|
||||
import { dataStoreColumnNameSchema } from '../../schemas/data-store.schema';
|
||||
import { paginationSchema } from 'dto/pagination/pagination.dto';
|
||||
import { paginationSchema } from '../pagination/pagination.dto';
|
||||
|
||||
const FilterConditionSchema = z.union([z.literal('eq'), z.literal('neq')]);
|
||||
export type ListDataStoreContentFilterConditionType = z.infer<typeof FilterConditionSchema>;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { paginationSchema } from 'dto/pagination/pagination.dto';
|
||||
import { jsonParse } from 'n8n-workflow';
|
||||
import { z } from 'zod';
|
||||
import { Z } from 'zod-class';
|
||||
|
||||
import { paginationSchema } from '../pagination/pagination.dto';
|
||||
|
||||
const VALID_SORT_OPTIONS = [
|
||||
'name:asc',
|
||||
'name:desc',
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const dataStoreColumnTypeSchema = z.enum(['string', 'number', 'boolean',
|
|||
export const dataStoreCreateColumnSchema = z.object({
|
||||
name: dataStoreColumnNameSchema,
|
||||
type: dataStoreColumnTypeSchema,
|
||||
columnIndex: z.number().optional(),
|
||||
});
|
||||
export type DataStoreCreateColumnSchema = z.infer<typeof dataStoreCreateColumnSchema>;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export class CreateDataStoreTables1747814180618 implements ReversibleMigration {
|
|||
column('id').varchar(36).primary.notNull,
|
||||
column('name').varchar(128).notNull,
|
||||
column('type').varchar(32).notNull,
|
||||
column('columnIndex').int.notNull,
|
||||
column('dataStoreId').varchar(36).notNull,
|
||||
)
|
||||
.withForeignKey('dataStoreId', {
|
||||
|
|
|
|||
|
|
@ -154,15 +154,14 @@ describe('dataStore', () => {
|
|||
it('should fail with adding two columns of the same name', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, {
|
||||
column: { name: 'myColumn1', type: 'string' },
|
||||
name: 'myColumn1',
|
||||
type: 'string',
|
||||
});
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.addColumn(dataStore1.id, {
|
||||
column: {
|
||||
name: 'myColumn1',
|
||||
type: 'number',
|
||||
},
|
||||
name: 'myColumn1',
|
||||
type: 'number',
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
|
|
@ -172,10 +171,8 @@ describe('dataStore', () => {
|
|||
it('should fail with adding column of non-existent table', async () => {
|
||||
// ACT
|
||||
const result = await dataStoreService.addColumn('this is not an id', {
|
||||
column: {
|
||||
name: 'myColumn1',
|
||||
type: 'number',
|
||||
},
|
||||
name: 'myColumn1',
|
||||
type: 'number',
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
|
|
@ -186,7 +183,8 @@ describe('dataStore', () => {
|
|||
it('should succeed with deleting a column', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, {
|
||||
column: { name: 'myColumn1', type: 'string' },
|
||||
name: 'myColumn1',
|
||||
type: 'string',
|
||||
});
|
||||
|
||||
// ACT
|
||||
|
|
@ -200,7 +198,8 @@ describe('dataStore', () => {
|
|||
it('should fail when deleting unknown column', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, {
|
||||
column: { name: 'myColumn1', type: 'string' },
|
||||
name: 'myColumn1',
|
||||
type: 'string',
|
||||
});
|
||||
|
||||
// ACT
|
||||
|
|
@ -214,7 +213,8 @@ describe('dataStore', () => {
|
|||
it('should fail when deleting column from unknown table', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, {
|
||||
column: { name: 'myColumn1', type: 'string' },
|
||||
name: 'myColumn1',
|
||||
type: 'string',
|
||||
});
|
||||
|
||||
// ACT
|
||||
|
|
@ -436,10 +436,10 @@ describe('dataStore', () => {
|
|||
describe('appendRows', () => {
|
||||
it('appends a row to an existing table', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.appendRows(dataStore1.id, [
|
||||
|
|
@ -454,10 +454,10 @@ describe('dataStore', () => {
|
|||
|
||||
it('rejects a mismatched row with extra column', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.appendRows(dataStore1.id, [
|
||||
|
|
@ -470,10 +470,10 @@ describe('dataStore', () => {
|
|||
});
|
||||
it('rejects a mismatched row with missing column', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.appendRows(dataStore1.id, [
|
||||
|
|
@ -486,10 +486,10 @@ describe('dataStore', () => {
|
|||
});
|
||||
it('rejects a mismatched row with replaced column', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.appendRows(dataStore1.id, [
|
||||
|
|
@ -502,10 +502,10 @@ describe('dataStore', () => {
|
|||
});
|
||||
it('rejects unknown data store id', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
// ACT
|
||||
const result = await dataStoreService.appendRows('this is not an id', [
|
||||
|
|
@ -530,10 +530,10 @@ describe('dataStore', () => {
|
|||
describe('getManyRowsAndCount', () => {
|
||||
it('retrieves rows correctly', async () => {
|
||||
// ARRANGE
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c1', type: 'number' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c2', type: 'boolean' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c3', type: 'date' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { column: { name: 'c4', type: 'string' } });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c1', type: 'number' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c2', type: 'boolean' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c3', type: 'date' });
|
||||
await dataStoreService.addColumn(dataStore1.id, { name: 'c4', type: 'string' });
|
||||
|
||||
await dataStoreService.appendRows(dataStore1.id, [
|
||||
{ c1: 3, c2: true, c3: new Date(0), c4: 'hello?' },
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { DataStoreCreateColumnSchema } from '@n8n/api-types/src/schemas/data-store.schema';
|
||||
import { WithStringId } from '@n8n/db';
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from '@n8n/typeorm';
|
||||
|
||||
import { type DataStoreEntity } from './data-store.entity';
|
||||
import { DataStoreColumnType } from './data-store.types';
|
||||
|
||||
@Entity()
|
||||
@Index(['dataStoreId', 'name'], { unique: true })
|
||||
|
|
@ -11,10 +11,13 @@ export class DataStoreColumnEntity extends WithStringId {
|
|||
dataStoreId: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
name: DataStoreCreateColumnSchema['name'];
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
type: DataStoreColumnType;
|
||||
type: DataStoreCreateColumnSchema['type'];
|
||||
|
||||
@Column({ type: 'int' })
|
||||
columnIndex: number;
|
||||
|
||||
@ManyToOne('DataStoreEntity', 'columns')
|
||||
@JoinColumn({ name: 'dataStoreId' })
|
||||
|
|
|
|||
|
|
@ -25,4 +25,17 @@ export class DataStoreColumnRepository extends Repository<DataStoreColumnEntity>
|
|||
async deleteColumn(dataStoreId: DataStoreUserTableName, column: string) {
|
||||
await this.manager.query(deleteColumnQuery(dataStoreId, column));
|
||||
}
|
||||
|
||||
async shiftColumns(dataStoreId: string, lowestIndex: number, delta: -1 | 1) {
|
||||
await this.createQueryBuilder()
|
||||
.update()
|
||||
.set({
|
||||
columnIndex: () => `columnIndex + ${delta}`,
|
||||
})
|
||||
.where('dataStoreId = :dataStoreId AND columnIndex > :thresholdValue', {
|
||||
dataStoreId,
|
||||
thresholdValue: lowestIndex,
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,13 +145,8 @@ export class DataStoreService {
|
|||
return 'tried to add column to non-existent table';
|
||||
}
|
||||
|
||||
const column = this.dataStoreColumnRepository.create({
|
||||
...dto.column,
|
||||
dataStoreId,
|
||||
});
|
||||
|
||||
const existingColumnMatch = await this.dataStoreColumnRepository.findBy({
|
||||
name: column.name,
|
||||
name: dto.name,
|
||||
dataStoreId,
|
||||
});
|
||||
|
||||
|
|
@ -159,6 +154,18 @@ export class DataStoreService {
|
|||
return 'tried to add column with name already present in this data store';
|
||||
}
|
||||
|
||||
if (dto.columnIndex === undefined) {
|
||||
const columns = await this.dataStoreColumnRepository.getColumns(dataStoreId);
|
||||
dto.columnIndex = columns.length;
|
||||
} else {
|
||||
await this.dataStoreColumnRepository.shiftColumns(dataStoreId, dto.columnIndex, 1);
|
||||
}
|
||||
|
||||
const column = this.dataStoreColumnRepository.create({
|
||||
...dto,
|
||||
dataStoreId,
|
||||
});
|
||||
|
||||
await this.dataStoreColumnRepository.insert(column);
|
||||
await this.dataStoreColumnRepository.addColumn(toTableName(dataStoreId), column);
|
||||
|
||||
|
|
@ -185,6 +192,11 @@ export class DataStoreService {
|
|||
|
||||
await this.dataStoreColumnRepository.remove(existingColumnMatch);
|
||||
await this.dataStoreColumnRepository.deleteColumn(toTableName(dataStoreId), dto.columnName);
|
||||
await this.dataStoreColumnRepository.shiftColumns(
|
||||
dataStoreId,
|
||||
existingColumnMatch[0].columnIndex,
|
||||
-1,
|
||||
);
|
||||
// should we update the main table entry's `updatedAt` field here?
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user