From f5df5fa98d02c83e131943e7eb2c2d546a42df02 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 2 Dec 2025 14:40:17 -0600 Subject: [PATCH] chore: change workflow column name (#24349) chore-change-workflow-column-name --- .../lib/model/workflow_action_item_dto.dart | Bin 3688 -> 3760 bytes .../model/workflow_action_response_dto.dart | Bin 4089 -> 4161 bytes .../lib/model/workflow_filter_item_dto.dart | Bin 3688 -> 3760 bytes .../model/workflow_filter_response_dto.dart | Bin 4089 -> 4161 bytes open-api/immich-openapi-specs.json | 24 ++++---- open-api/typescript-sdk/src/fetch-client.ts | 8 +-- server/src/database.ts | 4 +- server/src/dtos/workflow.dto.ts | 12 ++-- ...05680041-ChangeWorkflowTableColumnsName.ts | 27 +++++++++ server/src/schema/tables/workflow.table.ts | 8 +-- server/src/services/plugin.service.ts | 8 +-- server/src/services/workflow.service.ts | 16 +++--- .../specs/services/workflow.service.spec.ts | 52 +++++++++--------- 13 files changed, 93 insertions(+), 66 deletions(-) create mode 100644 server/src/schema/migrations/1764705680041-ChangeWorkflowTableColumnsName.ts diff --git a/mobile/openapi/lib/model/workflow_action_item_dto.dart b/mobile/openapi/lib/model/workflow_action_item_dto.dart index ee0b30216d75d4acb76dbb13301e592990b08c37..cb0c39eae965d484a22875c222ed11107c7a7e20 100644 GIT binary patch delta 192 zcmaDMvq5&l4o3EZoYM5nJjcyD8T;X!Nh}hR6PYJTLgkW6GV}91Qxt4%6`&%MSSG4-GBqOs}4=TQyo9!3e;>m0r8Zd)5>vO2Fp*cZa Ohf6`B)|#u9iwgi=FG9Wm delta 118 zcmdlW`$A^J4o1er&HEYqfz;$s=2g6j$t9Wjd7dc>wzdk1lOJqsGBS(x5;r@t{Q?=|#GwH+vyelL4WUYhOF^O5nyZ$J3jkvWCA$Cs diff --git a/mobile/openapi/lib/model/workflow_action_response_dto.dart b/mobile/openapi/lib/model/workflow_action_response_dto.dart index 6528f018c98bfeda4a4bac97bbfefd7279adcd8c..5132623e896dedcab90be73cc379ef17003a085d 100644 GIT binary patch delta 264 zcmewKGo<&R!RlltYDt|LGDF6&OoLAv48RB{M}wA-^akwa8WlOl{U>Wn`3wsZozr zuvI9@$Sl@_iC9loVDsC&m`#xhXn_u=1~*JXT~l%LE{^QY`J5Bj5H9`BFE3i2UzDAe UlV9$cqOQZGpipbgRm;T%04r`w&j0`b diff --git a/mobile/openapi/lib/model/workflow_filter_item_dto.dart b/mobile/openapi/lib/model/workflow_filter_item_dto.dart index 5b78585c3d76522fabeb165167143257cbae3a92..bd8090b05efad2541a553fc9417206f4278b64ee 100644 GIT binary patch delta 192 zcmaDMvq5&l4o3EZoYM5nJh#m|8T;X!Nh}hR6PYJTLgg}ZN>YnFQxt4%6`&%MSSG4-GBqOs}4=TQyo9!3e;>m0r8Zd)5>vO2Fp*cZa Ohf6`B)|#u9iwgjGX+s78 delta 118 zcmdlW`$A^J4o1eb&HEYqfz;$s=2g6DnK>n?MV=`NwzdjslOJqsGBS(x(l$G?{Q?=|#GwH+vyelL4WUYhOF^O5nyZ$J3jlQ}CIbKf diff --git a/mobile/openapi/lib/model/workflow_filter_response_dto.dart b/mobile/openapi/lib/model/workflow_filter_response_dto.dart index 5257c92b80ef96ce34007199ff3302d0c228db78..94dce27a3f0b7eec5afa3122a03b0839d3379249 100644 GIT binary patch delta 264 zcmewKGo<&R!RlltYDt|LGDF6&OoLAv48RB{M}wA-^akwa8WlOl{U>Wn`3wsZozr zuvI9@$Sl@_iC9loVDsC&m`#xhXn_u=1~*JXT~l%LE{^QY`J5Bj5H9`BFE3i2UzDAe UlV9$cqOQZGpipbgRm;T%09iLoDF6Tf diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 68af1438c..e21cf27be 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -23162,13 +23162,13 @@ "actionConfig": { "type": "object" }, - "actionId": { + "pluginActionId": { "format": "uuid", "type": "string" } }, "required": [ - "actionId" + "pluginActionId" ], "type": "object" }, @@ -23178,24 +23178,24 @@ "nullable": true, "type": "object" }, - "actionId": { - "type": "string" - }, "id": { "type": "string" }, "order": { "type": "number" }, + "pluginActionId": { + "type": "string" + }, "workflowId": { "type": "string" } }, "required": [ "actionConfig", - "actionId", "id", "order", + "pluginActionId", "workflowId" ], "type": "object" @@ -23244,13 +23244,13 @@ "filterConfig": { "type": "object" }, - "filterId": { + "pluginFilterId": { "format": "uuid", "type": "string" } }, "required": [ - "filterId" + "pluginFilterId" ], "type": "object" }, @@ -23260,24 +23260,24 @@ "nullable": true, "type": "object" }, - "filterId": { - "type": "string" - }, "id": { "type": "string" }, "order": { "type": "number" }, + "pluginFilterId": { + "type": "string" + }, "workflowId": { "type": "string" } }, "required": [ "filterConfig", - "filterId", "id", "order", + "pluginFilterId", "workflowId" ], "type": "object" diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index bbcc2311b..7afee42e2 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1729,16 +1729,16 @@ export type CreateProfileImageResponseDto = { }; export type WorkflowActionResponseDto = { actionConfig: object | null; - actionId: string; id: string; order: number; + pluginActionId: string; workflowId: string; }; export type WorkflowFilterResponseDto = { filterConfig: object | null; - filterId: string; id: string; order: number; + pluginFilterId: string; workflowId: string; }; export type WorkflowResponseDto = { @@ -1754,11 +1754,11 @@ export type WorkflowResponseDto = { }; export type WorkflowActionItemDto = { actionConfig?: object; - actionId: string; + pluginActionId: string; }; export type WorkflowFilterItemDto = { filterConfig?: object; - filterId: string; + pluginFilterId: string; }; export type WorkflowCreateDto = { actions: WorkflowActionItemDto[]; diff --git a/server/src/database.ts b/server/src/database.ts index 8e18fa940..a3c38ae61 100644 --- a/server/src/database.ts +++ b/server/src/database.ts @@ -301,14 +301,14 @@ export type Workflow = Selectable & { export type WorkflowFilter = Selectable & { workflowId: string; - filterId: string; + pluginFilterId: string; filterConfig: FilterConfig | null; order: number; }; export type WorkflowAction = Selectable & { workflowId: string; - actionId: string; + pluginActionId: string; actionConfig: ActionConfig | null; order: number; }; diff --git a/server/src/dtos/workflow.dto.ts b/server/src/dtos/workflow.dto.ts index 307440945..7bfb90e11 100644 --- a/server/src/dtos/workflow.dto.ts +++ b/server/src/dtos/workflow.dto.ts @@ -7,7 +7,7 @@ import { Optional, ValidateBoolean, ValidateEnum } from 'src/validation'; export class WorkflowFilterItemDto { @IsUUID() - filterId!: string; + pluginFilterId!: string; @IsObject() @Optional() @@ -16,7 +16,7 @@ export class WorkflowFilterItemDto { export class WorkflowActionItemDto { @IsUUID() - actionId!: string; + pluginActionId!: string; @IsObject() @Optional() @@ -86,7 +86,7 @@ export class WorkflowResponseDto { export class WorkflowFilterResponseDto { id!: string; workflowId!: string; - filterId!: string; + pluginFilterId!: string; filterConfig!: FilterConfig | null; order!: number; } @@ -94,7 +94,7 @@ export class WorkflowFilterResponseDto { export class WorkflowActionResponseDto { id!: string; workflowId!: string; - actionId!: string; + pluginActionId!: string; actionConfig!: ActionConfig | null; order!: number; } @@ -103,7 +103,7 @@ export function mapWorkflowFilter(filter: WorkflowFilter): WorkflowFilterRespons return { id: filter.id, workflowId: filter.workflowId, - filterId: filter.filterId, + pluginFilterId: filter.pluginFilterId, filterConfig: filter.filterConfig, order: filter.order, }; @@ -113,7 +113,7 @@ export function mapWorkflowAction(action: WorkflowAction): WorkflowActionRespons return { id: action.id, workflowId: action.workflowId, - actionId: action.actionId, + pluginActionId: action.pluginActionId, actionConfig: action.actionConfig, order: action.order, }; diff --git a/server/src/schema/migrations/1764705680041-ChangeWorkflowTableColumnsName.ts b/server/src/schema/migrations/1764705680041-ChangeWorkflowTableColumnsName.ts new file mode 100644 index 000000000..c495d2a8e --- /dev/null +++ b/server/src/schema/migrations/1764705680041-ChangeWorkflowTableColumnsName.ts @@ -0,0 +1,27 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely): Promise { + await sql`DROP INDEX "workflow_filter_filterId_idx";`.execute(db); + await sql`DROP INDEX "workflow_action_actionId_idx";`.execute(db); + await sql`ALTER TABLE "workflow_filter" DROP CONSTRAINT "workflow_filter_filterId_fkey";`.execute(db); + await sql`ALTER TABLE "workflow_action" DROP CONSTRAINT "workflow_action_actionId_fkey";`.execute(db); + await sql`ALTER TABLE "workflow_filter" RENAME COLUMN "filterId" TO "pluginFilterId";`.execute(db); + await sql`ALTER TABLE "workflow_action" RENAME COLUMN "actionId" TO "pluginActionId";`.execute(db); + await sql`ALTER TABLE "workflow_filter" ADD CONSTRAINT "workflow_filter_pluginFilterId_fkey" FOREIGN KEY ("pluginFilterId") REFERENCES "plugin_filter" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db); + await sql`ALTER TABLE "workflow_action" ADD CONSTRAINT "workflow_action_pluginActionId_fkey" FOREIGN KEY ("pluginActionId") REFERENCES "plugin_action" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db); + await sql`CREATE INDEX "workflow_filter_pluginFilterId_idx" ON "workflow_filter" ("pluginFilterId");`.execute(db); + await sql`CREATE INDEX "workflow_action_pluginActionId_idx" ON "workflow_action" ("pluginActionId");`.execute(db); +} + +export async function down(db: Kysely): Promise { + await sql`DROP INDEX "workflow_filter_pluginFilterId_idx";`.execute(db); + await sql`DROP INDEX "workflow_action_pluginActionId_idx";`.execute(db); + await sql`ALTER TABLE "workflow_filter" DROP CONSTRAINT "workflow_filter_pluginFilterId_fkey";`.execute(db); + await sql`ALTER TABLE "workflow_action" DROP CONSTRAINT "workflow_action_pluginActionId_fkey";`.execute(db); + await sql`ALTER TABLE "workflow_filter" RENAME COLUMN "pluginFilterId" TO "filterId";`.execute(db); + await sql`ALTER TABLE "workflow_action" RENAME COLUMN "pluginActionId" TO "actionId";`.execute(db); + await sql`ALTER TABLE "workflow_filter" ADD CONSTRAINT "workflow_filter_filterId_fkey" FOREIGN KEY ("filterId") REFERENCES "plugin_filter" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db); + await sql`ALTER TABLE "workflow_action" ADD CONSTRAINT "workflow_action_actionId_fkey" FOREIGN KEY ("actionId") REFERENCES "plugin_action" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db); + await sql`CREATE INDEX "workflow_filter_filterId_idx" ON "workflow_filter" ("filterId");`.execute(db); + await sql`CREATE INDEX "workflow_action_actionId_idx" ON "workflow_action" ("actionId");`.execute(db); +} diff --git a/server/src/schema/tables/workflow.table.ts b/server/src/schema/tables/workflow.table.ts index 8f7c9adb0..62a5531d8 100644 --- a/server/src/schema/tables/workflow.table.ts +++ b/server/src/schema/tables/workflow.table.ts @@ -38,7 +38,7 @@ export class WorkflowTable { } @Index({ columns: ['workflowId', 'order'] }) -@Index({ columns: ['filterId'] }) +@Index({ columns: ['pluginFilterId'] }) @Table('workflow_filter') export class WorkflowFilterTable { @PrimaryGeneratedColumn('uuid') @@ -48,7 +48,7 @@ export class WorkflowFilterTable { workflowId!: Generated; @ForeignKeyColumn(() => PluginFilterTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - filterId!: string; + pluginFilterId!: string; @Column({ type: 'jsonb', nullable: true }) filterConfig!: FilterConfig | null; @@ -58,7 +58,7 @@ export class WorkflowFilterTable { } @Index({ columns: ['workflowId', 'order'] }) -@Index({ columns: ['actionId'] }) +@Index({ columns: ['pluginActionId'] }) @Table('workflow_action') export class WorkflowActionTable { @PrimaryGeneratedColumn('uuid') @@ -68,7 +68,7 @@ export class WorkflowActionTable { workflowId!: Generated; @ForeignKeyColumn(() => PluginActionTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) - actionId!: string; + pluginActionId!: string; @Column({ type: 'jsonb', nullable: true }) actionConfig!: ActionConfig | null; diff --git a/server/src/services/plugin.service.ts b/server/src/services/plugin.service.ts index 28d1ac56c..9336f0003 100644 --- a/server/src/services/plugin.service.ts +++ b/server/src/services/plugin.service.ts @@ -247,9 +247,9 @@ export class PluginService extends BaseService { private async executeFilters(workflowFilters: WorkflowFilter[], context: WorkflowContext): Promise { for (const workflowFilter of workflowFilters) { - const filter = await this.pluginRepository.getFilter(workflowFilter.filterId); + const filter = await this.pluginRepository.getFilter(workflowFilter.pluginFilterId); if (!filter) { - this.logger.error(`Filter ${workflowFilter.filterId} not found`); + this.logger.error(`Filter ${workflowFilter.pluginFilterId} not found`); return false; } @@ -291,9 +291,9 @@ export class PluginService extends BaseService { private async executeActions(workflowActions: WorkflowAction[], context: WorkflowContext): Promise { for (const workflowAction of workflowActions) { - const action = await this.pluginRepository.getAction(workflowAction.actionId); + const action = await this.pluginRepository.getAction(workflowAction.pluginActionId); if (!action) { - throw new Error(`Action ${workflowAction.actionId} not found`); + throw new Error(`Action ${workflowAction.pluginActionId} not found`); } const pluginInstance = this.loadedPlugins.get(action.pluginId); diff --git a/server/src/services/workflow.service.ts b/server/src/services/workflow.service.ts index ae72187d7..301931421 100644 --- a/server/src/services/workflow.service.ts +++ b/server/src/services/workflow.service.ts @@ -78,13 +78,13 @@ export class WorkflowService extends BaseService { } private async validateAndMapFilters( - filters: Array<{ filterId: string; filterConfig?: any }>, + filters: Array<{ pluginFilterId: string; filterConfig?: any }>, requiredContext: PluginContext, ) { for (const dto of filters) { - const filter = await this.pluginRepository.getFilter(dto.filterId); + const filter = await this.pluginRepository.getFilter(dto.pluginFilterId); if (!filter) { - throw new BadRequestException(`Invalid filter ID: ${dto.filterId}`); + throw new BadRequestException(`Invalid filter ID: ${dto.pluginFilterId}`); } if (!filter.supportedContexts.includes(requiredContext)) { @@ -95,20 +95,20 @@ export class WorkflowService extends BaseService { } return filters.map((dto, index) => ({ - filterId: dto.filterId, + pluginFilterId: dto.pluginFilterId, filterConfig: dto.filterConfig || null, order: index, })); } private async validateAndMapActions( - actions: Array<{ actionId: string; actionConfig?: any }>, + actions: Array<{ pluginActionId: string; actionConfig?: any }>, requiredContext: PluginContext, ) { for (const dto of actions) { - const action = await this.pluginRepository.getAction(dto.actionId); + const action = await this.pluginRepository.getAction(dto.pluginActionId); if (!action) { - throw new BadRequestException(`Invalid action ID: ${dto.actionId}`); + throw new BadRequestException(`Invalid action ID: ${dto.pluginActionId}`); } if (!action.supportedContexts.includes(requiredContext)) { throw new BadRequestException( @@ -118,7 +118,7 @@ export class WorkflowService extends BaseService { } return actions.map((dto, index) => ({ - actionId: dto.actionId, + pluginActionId: dto.pluginActionId, actionConfig: dto.actionConfig || null, order: index, })); diff --git a/server/test/medium/specs/services/workflow.service.spec.ts b/server/test/medium/specs/services/workflow.service.spec.ts index aaf1c8b9e..1fddc2a7c 100644 --- a/server/test/medium/specs/services/workflow.service.spec.ts +++ b/server/test/medium/specs/services/workflow.service.spec.ts @@ -113,13 +113,13 @@ describe(WorkflowService.name, () => { enabled: true, filters: [ { - filterId: testFilterId, + pluginFilterId: testFilterId, filterConfig: { key: 'value' }, }, ], actions: [ { - actionId: testActionId, + pluginActionId: testActionId, actionConfig: { action: 'test' }, }, ], @@ -137,7 +137,7 @@ describe(WorkflowService.name, () => { expect(workflow.filters[0]).toMatchObject({ id: expect.any(String), workflowId: workflow.id, - filterId: testFilterId, + pluginFilterId: testFilterId, filterConfig: { key: 'value' }, order: 0, }); @@ -146,7 +146,7 @@ describe(WorkflowService.name, () => { expect(workflow.actions[0]).toMatchObject({ id: expect.any(String), workflowId: workflow.id, - actionId: testActionId, + pluginActionId: testActionId, actionConfig: { action: 'test' }, order: 0, }); @@ -163,7 +163,7 @@ describe(WorkflowService.name, () => { name: 'invalid-workflow', description: 'A workflow with invalid filter', enabled: true, - filters: [{ filterId: factory.uuid(), filterConfig: { key: 'value' } }], + filters: [{ pluginFilterId: factory.uuid(), filterConfig: { key: 'value' } }], actions: [], }), ).rejects.toThrow('Invalid filter ID'); @@ -181,7 +181,7 @@ describe(WorkflowService.name, () => { description: 'A workflow with invalid action', enabled: true, filters: [], - actions: [{ actionId: factory.uuid(), actionConfig: { action: 'test' } }], + actions: [{ pluginActionId: factory.uuid(), actionConfig: { action: 'test' } }], }), ).rejects.toThrow('Invalid action ID'); }); @@ -220,7 +220,7 @@ describe(WorkflowService.name, () => { name: 'invalid-context-workflow', description: 'A workflow with context mismatch', enabled: true, - filters: [{ filterId: result.filters[0].id }], + filters: [{ pluginFilterId: result.filters[0].id }], actions: [], }), ).rejects.toThrow('does not support asset context'); @@ -261,7 +261,7 @@ describe(WorkflowService.name, () => { description: 'A workflow with context mismatch', enabled: true, filters: [], - actions: [{ actionId: result.actions[0].id }], + actions: [{ pluginActionId: result.actions[0].id }], }), ).rejects.toThrow('does not support asset context'); }); @@ -277,13 +277,13 @@ describe(WorkflowService.name, () => { description: 'A workflow with multiple filters and actions', enabled: true, filters: [ - { filterId: testFilterId, filterConfig: { step: 1 } }, - { filterId: testFilterId, filterConfig: { step: 2 } }, + { pluginFilterId: testFilterId, filterConfig: { step: 1 } }, + { pluginFilterId: testFilterId, filterConfig: { step: 2 } }, ], actions: [ - { actionId: testActionId, actionConfig: { step: 1 } }, - { actionId: testActionId, actionConfig: { step: 2 } }, - { actionId: testActionId, actionConfig: { step: 3 } }, + { pluginActionId: testActionId, actionConfig: { step: 1 } }, + { pluginActionId: testActionId, actionConfig: { step: 2 } }, + { pluginActionId: testActionId, actionConfig: { step: 3 } }, ], }); @@ -378,8 +378,8 @@ describe(WorkflowService.name, () => { name: 'test-workflow', description: 'A test workflow', enabled: true, - filters: [{ filterId: testFilterId, filterConfig: { key: 'value' } }], - actions: [{ actionId: testActionId, actionConfig: { action: 'test' } }], + filters: [{ pluginFilterId: testFilterId, filterConfig: { key: 'value' } }], + actions: [{ pluginActionId: testActionId, actionConfig: { action: 'test' } }], }); const workflow = await sut.get(auth, created.id); @@ -461,14 +461,14 @@ describe(WorkflowService.name, () => { name: 'test-workflow', description: 'Test', enabled: true, - filters: [{ filterId: testFilterId, filterConfig: { old: 'config' } }], + filters: [{ pluginFilterId: testFilterId, filterConfig: { old: 'config' } }], actions: [], }); const updated = await sut.update(auth, created.id, { filters: [ - { filterId: testFilterId, filterConfig: { new: 'config' } }, - { filterId: testFilterId, filterConfig: { second: 'filter' } }, + { pluginFilterId: testFilterId, filterConfig: { new: 'config' } }, + { pluginFilterId: testFilterId, filterConfig: { second: 'filter' } }, ], }); @@ -488,13 +488,13 @@ describe(WorkflowService.name, () => { description: 'Test', enabled: true, filters: [], - actions: [{ actionId: testActionId, actionConfig: { old: 'config' } }], + actions: [{ pluginActionId: testActionId, actionConfig: { old: 'config' } }], }); const updated = await sut.update(auth, created.id, { actions: [ - { actionId: testActionId, actionConfig: { new: 'config' } }, - { actionId: testActionId, actionConfig: { second: 'action' } }, + { pluginActionId: testActionId, actionConfig: { new: 'config' } }, + { pluginActionId: testActionId, actionConfig: { second: 'action' } }, ], }); @@ -513,7 +513,7 @@ describe(WorkflowService.name, () => { name: 'test-workflow', description: 'Test', enabled: true, - filters: [{ filterId: testFilterId, filterConfig: { key: 'value' } }], + filters: [{ pluginFilterId: testFilterId, filterConfig: { key: 'value' } }], actions: [], }); @@ -588,7 +588,7 @@ describe(WorkflowService.name, () => { await expect( sut.update(auth, created.id, { - filters: [{ filterId: factory.uuid(), filterConfig: {} }], + filters: [{ pluginFilterId: factory.uuid(), filterConfig: {} }], }), ).rejects.toThrow(); }); @@ -608,7 +608,7 @@ describe(WorkflowService.name, () => { }); await expect( - sut.update(auth, created.id, { actions: [{ actionId: factory.uuid(), actionConfig: {} }] }), + sut.update(auth, created.id, { actions: [{ pluginActionId: factory.uuid(), actionConfig: {} }] }), ).rejects.toThrow(); }); }); @@ -643,8 +643,8 @@ describe(WorkflowService.name, () => { name: 'test-workflow', description: 'Test', enabled: true, - filters: [{ filterId: testFilterId, filterConfig: {} }], - actions: [{ actionId: testActionId, actionConfig: {} }], + filters: [{ pluginFilterId: testFilterId, filterConfig: {} }], + actions: [{ pluginActionId: testActionId, actionConfig: {} }], }); await sut.delete(auth, workflow.id);