@atom8n/n8n 2.5.2 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -58,6 +58,7 @@ let CliController = CliController_1 = class CliController {
|
|
|
58
58
|
const fileData = body.workflowData;
|
|
59
59
|
const chatInput = body.chatInput;
|
|
60
60
|
const inputData = body.inputData;
|
|
61
|
+
const fileModifiedAt = body.fileModifiedAt;
|
|
61
62
|
this.logger.info(`[cli] inputData: ${inputData ? JSON.stringify(inputData) : '(none)'}`);
|
|
62
63
|
if (!fileData.nodes || !Array.isArray(fileData.nodes)) {
|
|
63
64
|
res.status(400).json({ error: 'Workflow does not contain valid nodes' });
|
|
@@ -70,13 +71,13 @@ let CliController = CliController_1 = class CliController {
|
|
|
70
71
|
this.logger.info(`[cli] Workflow: "${fileData.name}", Nodes: ${fileData.nodes.length}`);
|
|
71
72
|
try {
|
|
72
73
|
const user = await this.ownershipService.getInstanceOwner();
|
|
73
|
-
const
|
|
74
|
-
const workflow = await this.workflowRepository.findOneBy({ id:
|
|
74
|
+
const syncResult = await this.syncWorkflow(fileData, user.id, fileModifiedAt);
|
|
75
|
+
const workflow = await this.workflowRepository.findOneBy({ id: syncResult.id });
|
|
75
76
|
if (!workflow) {
|
|
76
77
|
res.status(500).json({ error: 'Failed to sync workflow to database' });
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
|
-
this.logger.info(`[cli] Synced workflow: "${workflow.name}" (ID: ${
|
|
80
|
+
this.logger.info(`[cli] Synced workflow: "${workflow.name}" (ID: ${syncResult.id})`);
|
|
80
81
|
const triggerNode = workflow.nodes.find((node) => node.type.toLowerCase().includes('trigger') ||
|
|
81
82
|
node.type.toLowerCase().includes('webhook') ||
|
|
82
83
|
node.type === 'n8n-nodes-base.start');
|
|
@@ -204,13 +205,17 @@ let CliController = CliController_1 = class CliController {
|
|
|
204
205
|
includeData: true,
|
|
205
206
|
unflattenData: true,
|
|
206
207
|
});
|
|
207
|
-
|
|
208
|
+
const responsePayload = {
|
|
208
209
|
success: isSuccess,
|
|
209
210
|
executionId,
|
|
210
211
|
status: runResult.status,
|
|
211
212
|
executionTime: totalTime,
|
|
212
213
|
data: fullExecution?.data?.resultData ?? runResult.data.resultData,
|
|
213
|
-
}
|
|
214
|
+
};
|
|
215
|
+
if (syncResult.syncedWorkflow) {
|
|
216
|
+
responsePayload.syncedWorkflow = syncResult.syncedWorkflow;
|
|
217
|
+
}
|
|
218
|
+
res.json(responsePayload);
|
|
214
219
|
}
|
|
215
220
|
catch (error) {
|
|
216
221
|
if (timeoutId)
|
|
@@ -228,17 +233,19 @@ let CliController = CliController_1 = class CliController {
|
|
|
228
233
|
});
|
|
229
234
|
}
|
|
230
235
|
}
|
|
231
|
-
async syncWorkflow(fileData, userId) {
|
|
236
|
+
async syncWorkflow(fileData, userId, fileModifiedAt) {
|
|
232
237
|
if (fileData.id && (0, utils_1.isWorkflowIdValid)(fileData.id)) {
|
|
233
238
|
const existing = await this.workflowRepository.findOneBy({ id: fileData.id });
|
|
234
239
|
if (existing) {
|
|
235
|
-
const fileUpdatedAt =
|
|
236
|
-
? new Date(fileData.updatedAt)
|
|
237
|
-
: null;
|
|
240
|
+
const fileUpdatedAt = fileModifiedAt ? new Date(fileModifiedAt) : null;
|
|
238
241
|
const serverUpdatedAt = existing.updatedAt
|
|
239
242
|
? new Date(existing.updatedAt)
|
|
240
243
|
: null;
|
|
241
|
-
|
|
244
|
+
this.logger.info(`[cli] Found existing workflow (ID match): ${existing.id}, ` +
|
|
245
|
+
`fileUpdatedAt=${fileUpdatedAt?.toISOString() ?? 'null'}, ` +
|
|
246
|
+
`serverUpdatedAt=${serverUpdatedAt?.toISOString() ?? 'null'}`);
|
|
247
|
+
const shouldUpdate = !fileUpdatedAt || !serverUpdatedAt || fileUpdatedAt >= serverUpdatedAt;
|
|
248
|
+
if (shouldUpdate) {
|
|
242
249
|
this.logger.info(`[cli] Updating existing workflow (ID match): ${existing.id}`);
|
|
243
250
|
await this.workflowRepository.update(existing.id, {
|
|
244
251
|
nodes: fileData.nodes,
|
|
@@ -247,23 +254,36 @@ let CliController = CliController_1 = class CliController {
|
|
|
247
254
|
name: fileData.name,
|
|
248
255
|
updatedAt: new Date(),
|
|
249
256
|
});
|
|
257
|
+
return { id: existing.id };
|
|
250
258
|
}
|
|
251
259
|
else {
|
|
252
|
-
this.logger.info(`[cli] Using existing workflow (ID match): ${existing.id}`
|
|
260
|
+
this.logger.info(`[cli] Using existing workflow (ID match): ${existing.id} ` +
|
|
261
|
+
`(server is newer: ${serverUpdatedAt.toISOString()} > ${fileUpdatedAt.toISOString()})`);
|
|
262
|
+
return {
|
|
263
|
+
id: existing.id,
|
|
264
|
+
syncedWorkflow: {
|
|
265
|
+
name: existing.name,
|
|
266
|
+
nodes: existing.nodes,
|
|
267
|
+
connections: existing.connections,
|
|
268
|
+
settings: existing.settings,
|
|
269
|
+
pinData: existing.pinData ?? {},
|
|
270
|
+
},
|
|
271
|
+
};
|
|
253
272
|
}
|
|
254
|
-
return existing.id;
|
|
255
273
|
}
|
|
256
274
|
}
|
|
257
275
|
if (fileData.name) {
|
|
258
276
|
const existing = await this.workflowRepository.findOneBy({ name: fileData.name });
|
|
259
277
|
if (existing) {
|
|
260
|
-
const fileUpdatedAt =
|
|
261
|
-
? new Date(fileData.updatedAt)
|
|
262
|
-
: null;
|
|
278
|
+
const fileUpdatedAt = fileModifiedAt ? new Date(fileModifiedAt) : null;
|
|
263
279
|
const serverUpdatedAt = existing.updatedAt
|
|
264
280
|
? new Date(existing.updatedAt)
|
|
265
281
|
: null;
|
|
266
|
-
|
|
282
|
+
this.logger.info(`[cli] Found existing workflow (name match): ${existing.id}, ` +
|
|
283
|
+
`fileUpdatedAt=${fileUpdatedAt?.toISOString() ?? 'null'}, ` +
|
|
284
|
+
`serverUpdatedAt=${serverUpdatedAt?.toISOString() ?? 'null'}`);
|
|
285
|
+
const shouldUpdate = !fileUpdatedAt || !serverUpdatedAt || fileUpdatedAt >= serverUpdatedAt;
|
|
286
|
+
if (shouldUpdate) {
|
|
267
287
|
this.logger.info(`[cli] Updating existing workflow (name match): ${existing.id}`);
|
|
268
288
|
await this.workflowRepository.update(existing.id, {
|
|
269
289
|
nodes: fileData.nodes,
|
|
@@ -272,11 +292,22 @@ let CliController = CliController_1 = class CliController {
|
|
|
272
292
|
name: fileData.name,
|
|
273
293
|
updatedAt: new Date(),
|
|
274
294
|
});
|
|
295
|
+
return { id: existing.id };
|
|
275
296
|
}
|
|
276
297
|
else {
|
|
277
|
-
this.logger.info(`[cli] Using existing workflow (name match): ${existing.id}`
|
|
298
|
+
this.logger.info(`[cli] Using existing workflow (name match): ${existing.id} ` +
|
|
299
|
+
`(server is newer: ${serverUpdatedAt.toISOString()} > ${fileUpdatedAt.toISOString()})`);
|
|
300
|
+
return {
|
|
301
|
+
id: existing.id,
|
|
302
|
+
syncedWorkflow: {
|
|
303
|
+
name: existing.name,
|
|
304
|
+
nodes: existing.nodes,
|
|
305
|
+
connections: existing.connections,
|
|
306
|
+
settings: existing.settings,
|
|
307
|
+
pinData: existing.pinData ?? {},
|
|
308
|
+
},
|
|
309
|
+
};
|
|
278
310
|
}
|
|
279
|
-
return existing.id;
|
|
280
311
|
}
|
|
281
312
|
}
|
|
282
313
|
const workflowId = fileData.id && (0, utils_1.isWorkflowIdValid)(fileData.id) ? fileData.id : (0, db_1.generateNanoId)();
|
|
@@ -301,7 +332,7 @@ let CliController = CliController_1 = class CliController {
|
|
|
301
332
|
});
|
|
302
333
|
await transactionManager.save(sharedWorkflow);
|
|
303
334
|
});
|
|
304
|
-
return workflowId;
|
|
335
|
+
return { id: workflowId };
|
|
305
336
|
}
|
|
306
337
|
async health() {
|
|
307
338
|
return { status: 'ok', timestamp: new Date().toISOString() };
|