Przeglądaj źródła

fix: stop webui api mappers from silently dropping backend fields

transformGroup and transformWorkflow (plus the execution mappers) listed
backend fields one by one, so anything the server added after the mapper
was written was discarded on the way to the UI with no error - this is
how _version, projectId, and usedByWorkflows all went missing before.

Switch to spreading the response first and overriding only what needs a
rename or a conversion, matching the pattern already used in
credentials.ts. transformGroup gaining projectId is what the folder
move-to-project feature (next commit) needs.
fszontagh 1 miesiąc temu
rodzic
commit
6bd8e29c96
2 zmienionych plików z 19 dodań i 26 usunięć
  1. 9 3
      webui/src/api/workflowGroups.ts
  2. 10 23
      webui/src/api/workflows.ts

+ 9 - 3
webui/src/api/workflowGroups.ts

@@ -7,18 +7,24 @@ export interface WorkflowGroup {
   description?: string
   parentId?: string
   ownerId: string
+  /** The project this folder belongs to - who may see and change it, and everything in it. */
+  projectId?: string
   createdAt: number | null
   updatedAt: number | null
 }
 
 // Transform backend group data to frontend format
+//
+// Everything the server sent, then the handful of fields that need a
+// different name or a conversion. Listing fields one by one is how
+// projectId went missing here - the same pattern that dropped _version and
+// usedByWorkflows elsewhere. A mapper that names every field silently
+// discards every field added after it was written, and nothing fails.
 function transformGroup(data: any): WorkflowGroup {
   return {
+    ...data,
     id: data._id,
-    name: data.name,
-    description: data.description,
     parentId: data.parentId || undefined,
-    ownerId: data.ownerId,
     // Same snake_case nanosecond metadata as workflows - see utils/timestamps.
     createdAt: readTimestamp(data, '_created_at'),
     updatedAt: readTimestamp(data, '_updated_at'),

+ 10 - 23
webui/src/api/workflows.ts

@@ -73,14 +73,15 @@ export interface NodeDefinition {
 }
 
 // Transform backend workflow data to frontend format
+// Everything the server sent, then the handful of fields that need a
+// different name, a default, or a conversion. Listing fields one by one is
+// how this mapper dropped the record version before, and how projectId and
+// usedByWorkflows went missing elsewhere - a mapper that names every field
+// silently discards every field added after it was written, and nothing fails.
 function transformWorkflow(data: any): Workflow {
   return {
+    ...data,
     id: data._id,
-    name: data.name,
-    description: data.description,
-    active: data.active,
-    groupId: data.groupId,
-    projectId: data.projectId,
     nodes: data.nodes || [],
     connections: data.connections || [],
     settings: data.settings || {},
@@ -90,14 +91,12 @@ function transformWorkflow(data: any): Workflow {
     // workflow show "unknown" here in the first place.
     createdAt: readTimestamp(data, '_created_at'),
     updatedAt: readTimestamp(data, '_updated_at'),
-    ownerId: data.ownerId,
     // _created_by is present on the document but has been empty on every record
     // inspected so far, so ownerId is the field that actually identifies a
     // person. Kept here for when the backend starts populating it.
     createdBy: data._created_by || undefined,
     updatedBy: data._updated_by || undefined,
     version: typeof data._version === 'number' ? data._version : undefined,
-    hasUnpublishedChanges: data.hasUnpublishedChanges,
     publishedVersion: typeof data.publishedVersion === 'number' ? data.publishedVersion : undefined,
   }
 }
@@ -505,39 +504,27 @@ export interface ExecutionListItem {
   finishedAt: number
 }
 
-// Transform backend execution list item to frontend format
+// Transform backend execution list item to frontend format. Spread first, as
+// in transformWorkflow above, so a field added later is not silently dropped.
 function transformExecutionListItem(data: any): ExecutionListItem {
   return {
+    ...data,
     id: data._id,
-    workflowId: data.workflowId,
-    workflowName: data.workflowName,
-    status: data.status,
     triggerType: data.triggerType || '',
     runnerId: data.runnerId || '',
     error: data.error || '',
     stopReason: data.stopReason || undefined,
-    startedAt: data.startedAt,
-    finishedAt: data.finishedAt,
   }
 }
 
 // Transform backend execution detail to frontend format
 function transformExecutionDetail(data: any): ExecutionDetail {
   return {
+    ...data,
     id: data._id,
-    workflowId: data.workflowId,
-    workflowName: data.workflowName,
-    status: data.status,
-    triggerType: data.triggerType,
-    triggerData: data.triggerData,
-    startedAt: data.startedAt,
-    finishedAt: data.finishedAt,
     nodeExecutions: data.nodeExecutions || [],
-    error: data.error,
     stopReason: data.stopReason || undefined,
     stoppedNodeId: data.stoppedNodeId || undefined,
-    output: data.output,
-    workflowSnapshot: data.workflowSnapshot,
   }
 }