@n8n-as-code/core 0.2.0 → 0.3.0

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.
Files changed (40) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/services/hash-utils.d.ts +22 -0
  6. package/dist/services/hash-utils.d.ts.map +1 -0
  7. package/dist/services/hash-utils.js +31 -0
  8. package/dist/services/hash-utils.js.map +1 -0
  9. package/dist/services/n8n-api-client.d.ts.map +1 -1
  10. package/dist/services/n8n-api-client.js +44 -50
  11. package/dist/services/n8n-api-client.js.map +1 -1
  12. package/dist/services/resolution-manager.d.ts +73 -0
  13. package/dist/services/resolution-manager.d.ts.map +1 -0
  14. package/dist/services/resolution-manager.js +149 -0
  15. package/dist/services/resolution-manager.js.map +1 -0
  16. package/dist/services/state-manager.d.ts +18 -17
  17. package/dist/services/state-manager.d.ts.map +1 -1
  18. package/dist/services/state-manager.js +22 -53
  19. package/dist/services/state-manager.js.map +1 -1
  20. package/dist/services/sync-engine.d.ts +57 -0
  21. package/dist/services/sync-engine.d.ts.map +1 -0
  22. package/dist/services/sync-engine.js +301 -0
  23. package/dist/services/sync-engine.js.map +1 -0
  24. package/dist/services/sync-manager.d.ts +19 -83
  25. package/dist/services/sync-manager.d.ts.map +1 -1
  26. package/dist/services/sync-manager.js +208 -620
  27. package/dist/services/sync-manager.js.map +1 -1
  28. package/dist/services/watcher.d.ts +121 -0
  29. package/dist/services/watcher.d.ts.map +1 -0
  30. package/dist/services/watcher.js +609 -0
  31. package/dist/services/watcher.js.map +1 -0
  32. package/dist/services/workflow-sanitizer.d.ts +9 -4
  33. package/dist/services/workflow-sanitizer.d.ts.map +1 -1
  34. package/dist/services/workflow-sanitizer.js +55 -35
  35. package/dist/services/workflow-sanitizer.js.map +1 -1
  36. package/dist/types.d.ts +10 -5
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/types.js +8 -5
  39. package/dist/types.js.map +1 -1
  40. package/package.json +4 -2
@@ -0,0 +1,609 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import EventEmitter from 'events';
4
+ import * as chokidar from 'chokidar';
5
+ import { WorkflowSanitizer } from './workflow-sanitizer.js';
6
+ import { HashUtils } from './hash-utils.js';
7
+ import { WorkflowSyncStatus } from '../types.js';
8
+ /**
9
+ * Watcher - State Observation Component
10
+ *
11
+ * Responsibilities:
12
+ * 1. File System Watch with debounce
13
+ * 2. Remote Polling with lightweight strategy
14
+ * 3. Canonical Hashing (SHA-256 of sorted JSON)
15
+ * 4. Status Matrix Calculation (3-way comparison)
16
+ * 5. State Persistence (only component that writes to .n8n-state.json)
17
+ *
18
+ * Never performs synchronization actions - only observes reality.
19
+ */
20
+ export class Watcher extends EventEmitter {
21
+ watcher = null;
22
+ pollInterval = null;
23
+ client;
24
+ directory;
25
+ pollIntervalMs;
26
+ syncInactive;
27
+ ignoredTags;
28
+ stateFilePath;
29
+ isConnected = true;
30
+ isInitializing = false;
31
+ // Internal state tracking
32
+ localHashes = new Map(); // filename -> hash
33
+ remoteHashes = new Map(); // workflowId -> hash
34
+ fileToIdMap = new Map(); // filename -> workflowId
35
+ idToFileMap = new Map(); // workflowId -> filename
36
+ lastKnownStatuses = new Map(); // workflowId or filename -> status
37
+ // Concurrency control
38
+ isPaused = new Set(); // IDs for which observation is paused
39
+ syncInProgress = new Set(); // IDs currently being synced
40
+ // Lightweight polling cache
41
+ remoteTimestamps = new Map(); // workflowId -> updatedAt
42
+ constructor(client, options) {
43
+ super();
44
+ this.client = client;
45
+ this.directory = options.directory;
46
+ this.pollIntervalMs = options.pollIntervalMs;
47
+ this.syncInactive = options.syncInactive;
48
+ this.ignoredTags = options.ignoredTags;
49
+ this.stateFilePath = path.join(this.directory, '.n8n-state.json');
50
+ }
51
+ async start() {
52
+ if (this.watcher || this.pollInterval)
53
+ return;
54
+ this.isInitializing = true;
55
+ // Initial scan - throw error if connection fails on startup
56
+ try {
57
+ await this.refreshRemoteState();
58
+ }
59
+ catch (error) {
60
+ // Check if it's a connection error
61
+ const isConnectionError = error.code === 'ECONNREFUSED' ||
62
+ error.code === 'ENOTFOUND' ||
63
+ error.code === 'ETIMEDOUT' ||
64
+ error.message?.includes('fetch failed') ||
65
+ error.message?.includes('ECONNREFUSED') ||
66
+ error.message?.includes('ENOTFOUND') ||
67
+ error.cause?.code === 'ECONNREFUSED';
68
+ if (isConnectionError) {
69
+ this.isInitializing = false;
70
+ // On startup, throw the error to prevent initialization
71
+ throw new Error('Cannot connect to n8n instance. Please check if n8n is running and the host URL is correct.');
72
+ }
73
+ // For other errors, re-throw
74
+ this.isInitializing = false;
75
+ throw error;
76
+ }
77
+ await this.refreshLocalState();
78
+ this.isInitializing = false;
79
+ // Local Watch with debounce
80
+ this.watcher = chokidar.watch(this.directory, {
81
+ ignored: [
82
+ /(^|[\/\\])\../, // Hidden files
83
+ '**/_archive/**', // Archive folder (strictly ignored)
84
+ '**/.n8n-state.json' // State file
85
+ ],
86
+ persistent: true,
87
+ ignoreInitial: true,
88
+ awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 } // 500ms debounce
89
+ });
90
+ this.watcher
91
+ .on('add', (p) => this.onLocalChange(p))
92
+ .on('change', (p) => this.onLocalChange(p))
93
+ .on('unlink', (p) => this.onLocalDelete(p));
94
+ // Remote Poll
95
+ if (this.pollIntervalMs > 0) {
96
+ this.pollInterval = setInterval(() => this.refreshRemoteState(), this.pollIntervalMs);
97
+ }
98
+ this.emit('ready');
99
+ }
100
+ stop() {
101
+ if (this.watcher) {
102
+ this.watcher.close();
103
+ this.watcher = null;
104
+ }
105
+ if (this.pollInterval) {
106
+ clearInterval(this.pollInterval);
107
+ this.pollInterval = null;
108
+ }
109
+ }
110
+ /**
111
+ * Pause observation for a workflow during sync operations
112
+ */
113
+ pauseObservation(workflowId) {
114
+ this.isPaused.add(workflowId);
115
+ }
116
+ /**
117
+ * Resume observation after sync operations
118
+ */
119
+ resumeObservation(workflowId) {
120
+ this.isPaused.delete(workflowId);
121
+ // Force refresh to get latest state
122
+ this.refreshRemoteState();
123
+ }
124
+ /**
125
+ * Mark a workflow as being synced (prevents race conditions)
126
+ */
127
+ markSyncInProgress(workflowId) {
128
+ this.syncInProgress.add(workflowId);
129
+ }
130
+ /**
131
+ * Mark a workflow as no longer being synced
132
+ */
133
+ markSyncComplete(workflowId) {
134
+ this.syncInProgress.delete(workflowId);
135
+ }
136
+ async onLocalChange(filePath) {
137
+ const filename = path.basename(filePath);
138
+ if (!filename.endsWith('.json'))
139
+ return;
140
+ const content = this.readJsonFile(filePath);
141
+ if (!content)
142
+ return;
143
+ const workflowId = content.id || this.fileToIdMap.get(filename);
144
+ if (workflowId && (this.isPaused.has(workflowId) || this.syncInProgress.has(workflowId))) {
145
+ return;
146
+ }
147
+ // IMPORTANT: Hash is calculated on the SANITIZED version
148
+ // This means versionId, versionCounter, pinData, etc. are ignored
149
+ // The file on disk can contain these fields, but they won't affect the hash
150
+ const clean = WorkflowSanitizer.cleanForStorage(content);
151
+ const hash = this.computeHash(clean);
152
+ this.localHashes.set(filename, hash);
153
+ if (workflowId) {
154
+ this.fileToIdMap.set(filename, workflowId);
155
+ this.idToFileMap.set(workflowId, filename);
156
+ }
157
+ this.broadcastStatus(filename, workflowId);
158
+ }
159
+ async onLocalDelete(filePath) {
160
+ const filename = path.basename(filePath);
161
+ let workflowId = this.fileToIdMap.get(filename);
162
+ // If workflowId not found via filename mapping, try to find it via state
163
+ if (!workflowId) {
164
+ const state = this.loadState();
165
+ for (const [id, stateData] of Object.entries(state.workflows)) {
166
+ const mappedFilename = this.idToFileMap.get(id);
167
+ if (mappedFilename === filename) {
168
+ workflowId = id;
169
+ break;
170
+ }
171
+ }
172
+ }
173
+ if (workflowId && (this.isPaused.has(workflowId) || this.syncInProgress.has(workflowId))) {
174
+ return;
175
+ }
176
+ // CRITICAL: Per spec 5.3 DELETED_LOCALLY - Archive Remote to _archive/ IMMEDIATELY
177
+ // This happens BEFORE user confirmation, to ensure we have a backup
178
+ if (workflowId) {
179
+ const remoteHash = this.remoteHashes.get(workflowId);
180
+ const lastSyncedHash = this.getLastSyncedHash(workflowId);
181
+ // Only archive if remote exists and matches last synced (true local deletion)
182
+ if (remoteHash && remoteHash === lastSyncedHash) {
183
+ try {
184
+ // Fetch remote workflow content
185
+ const remoteWorkflow = await this.client.getWorkflow(workflowId);
186
+ if (remoteWorkflow) {
187
+ // Create archive directory if it doesn't exist
188
+ const archiveDir = path.join(this.directory, '.archive');
189
+ if (!fs.existsSync(archiveDir)) {
190
+ fs.mkdirSync(archiveDir, { recursive: true });
191
+ }
192
+ // Save to archive with timestamp
193
+ const clean = WorkflowSanitizer.cleanForStorage(remoteWorkflow);
194
+ const archivePath = path.join(archiveDir, `${Date.now()}_${filename}`);
195
+ fs.writeFileSync(archivePath, JSON.stringify(clean, null, 2));
196
+ console.log(`[Watcher] Archived remote workflow to: ${archivePath}`);
197
+ }
198
+ }
199
+ catch (error) {
200
+ console.warn(`[Watcher] Failed to archive remote workflow ${workflowId}:`, error);
201
+ // Continue anyway - deletion detection should still work
202
+ }
203
+ }
204
+ }
205
+ this.localHashes.delete(filename);
206
+ this.broadcastStatus(filename, workflowId);
207
+ }
208
+ async refreshLocalState() {
209
+ if (!fs.existsSync(this.directory)) {
210
+ console.log(`[DEBUG] refreshLocalState: Directory missing: ${this.directory}`);
211
+ // Clear all local hashes since directory doesn't exist
212
+ this.localHashes.clear();
213
+ return;
214
+ }
215
+ const files = fs.readdirSync(this.directory).filter(f => f.endsWith('.json') && !f.startsWith('.'));
216
+ const currentFiles = new Set(files);
217
+ // Remove entries for files that no longer exist
218
+ for (const filename of this.localHashes.keys()) {
219
+ if (!currentFiles.has(filename)) {
220
+ this.localHashes.delete(filename);
221
+ const workflowId = this.fileToIdMap.get(filename);
222
+ if (workflowId) {
223
+ // Broadcast status change for deleted file
224
+ this.broadcastStatus(filename, workflowId);
225
+ }
226
+ }
227
+ }
228
+ // Add/update entries for existing files
229
+ for (const filename of files) {
230
+ const filePath = path.join(this.directory, filename);
231
+ const content = this.readJsonFile(filePath);
232
+ if (content) {
233
+ const clean = WorkflowSanitizer.cleanForStorage(content);
234
+ const hash = this.computeHash(clean);
235
+ this.localHashes.set(filename, hash);
236
+ if (content.id) {
237
+ this.fileToIdMap.set(filename, content.id);
238
+ this.idToFileMap.set(content.id, filename);
239
+ }
240
+ }
241
+ }
242
+ }
243
+ /**
244
+ * Lightweight polling strategy:
245
+ * 1. Fetch only IDs and updatedAt timestamps
246
+ * 2. Compare with cached timestamps
247
+ * 3. Fetch full content only if timestamp changed
248
+ */
249
+ async refreshRemoteState() {
250
+ try {
251
+ const remoteWorkflows = await this.client.getAllWorkflows();
252
+ this.isConnected = true;
253
+ const currentRemoteIds = new Set();
254
+ for (const wf of remoteWorkflows) {
255
+ if (this.shouldIgnore(wf))
256
+ continue;
257
+ if (this.isPaused.has(wf.id) || this.syncInProgress.has(wf.id))
258
+ continue;
259
+ currentRemoteIds.add(wf.id);
260
+ const filename = `${this.safeName(wf.name)}.json`;
261
+ this.idToFileMap.set(wf.id, filename);
262
+ this.fileToIdMap.set(filename, wf.id);
263
+ // Check if we need to fetch full content
264
+ const cachedTimestamp = this.remoteTimestamps.get(wf.id);
265
+ const needsFullFetch = !cachedTimestamp ||
266
+ (wf.updatedAt && wf.updatedAt !== cachedTimestamp);
267
+ if (needsFullFetch) {
268
+ try {
269
+ const fullWf = await this.client.getWorkflow(wf.id);
270
+ if (fullWf) {
271
+ const clean = WorkflowSanitizer.cleanForStorage(fullWf);
272
+ const hash = this.computeHash(clean);
273
+ this.remoteHashes.set(wf.id, hash);
274
+ if (wf.updatedAt) {
275
+ this.remoteTimestamps.set(wf.id, wf.updatedAt);
276
+ }
277
+ this.broadcastStatus(filename, wf.id);
278
+ }
279
+ }
280
+ catch (e) {
281
+ console.warn(`[Watcher] Could not fetch workflow ${wf.id}:`, e);
282
+ }
283
+ }
284
+ else {
285
+ // Timestamp unchanged, use cached hash
286
+ const cachedHash = this.remoteHashes.get(wf.id);
287
+ if (cachedHash) {
288
+ this.broadcastStatus(filename, wf.id);
289
+ }
290
+ }
291
+ }
292
+ // Prune remoteHashes for deleted workflows
293
+ for (const id of this.remoteHashes.keys()) {
294
+ if (!currentRemoteIds.has(id)) {
295
+ this.remoteHashes.delete(id);
296
+ this.remoteTimestamps.delete(id);
297
+ const filename = this.idToFileMap.get(id);
298
+ if (filename)
299
+ this.broadcastStatus(filename, id);
300
+ }
301
+ }
302
+ }
303
+ catch (error) {
304
+ // Check if it's a connection error
305
+ const isConnectionError = error.code === 'ECONNREFUSED' ||
306
+ error.code === 'ENOTFOUND' ||
307
+ error.code === 'ETIMEDOUT' ||
308
+ error.message?.includes('fetch failed') ||
309
+ error.message?.includes('ECONNREFUSED') ||
310
+ error.message?.includes('ENOTFOUND') ||
311
+ error.cause?.code === 'ECONNREFUSED';
312
+ if (isConnectionError) {
313
+ this.isConnected = false;
314
+ // Stop polling to avoid spamming errors
315
+ if (this.pollInterval) {
316
+ clearInterval(this.pollInterval);
317
+ this.pollInterval = null;
318
+ }
319
+ // Emit a specific connection error
320
+ this.emit('connection-lost', new Error('Lost connection to n8n instance. Please check if n8n is running.'));
321
+ }
322
+ else {
323
+ // For other errors, just emit the error
324
+ this.emit('error', error);
325
+ }
326
+ // Re-throw so that start() can catch it on initial call
327
+ throw error;
328
+ }
329
+ }
330
+ /**
331
+ * Finalize sync - update base state after successful sync operation
332
+ * Called by SyncEngine after PULL/PUSH completes
333
+ */
334
+ async finalizeSync(workflowId) {
335
+ let filename = this.idToFileMap.get(workflowId);
336
+ // If workflow not tracked yet (first sync of local-only workflow),
337
+ // scan directory to find the file with this ID
338
+ if (!filename) {
339
+ const files = fs.readdirSync(this.directory).filter(f => f.endsWith('.json') && !f.startsWith('.'));
340
+ for (const file of files) {
341
+ const filePath = path.join(this.directory, file);
342
+ const content = this.readJsonFile(filePath);
343
+ if (content?.id === workflowId) {
344
+ filename = file;
345
+ // Initialize tracking for this workflow
346
+ this.fileToIdMap.set(filename, workflowId);
347
+ this.idToFileMap.set(workflowId, filename);
348
+ break;
349
+ }
350
+ }
351
+ if (!filename) {
352
+ throw new Error(`Cannot finalize sync: workflow ${workflowId} not found in directory`);
353
+ }
354
+ }
355
+ // Get current reality
356
+ const filePath = path.join(this.directory, filename);
357
+ const content = this.readJsonFile(filePath);
358
+ if (!content) {
359
+ throw new Error(`Cannot finalize sync: local file not found for ${workflowId}`);
360
+ }
361
+ const clean = WorkflowSanitizer.cleanForStorage(content);
362
+ const computedHash = this.computeHash(clean);
363
+ // After a successful sync, local and remote should be identical
364
+ // Use the computed hash for both
365
+ const localHash = computedHash;
366
+ const remoteHash = computedHash;
367
+ // Update caches
368
+ this.localHashes.set(filename, localHash);
369
+ this.remoteHashes.set(workflowId, remoteHash);
370
+ // Update base state
371
+ await this.updateWorkflowState(workflowId, localHash);
372
+ // Broadcast new IN_SYNC status
373
+ this.broadcastStatus(filename, workflowId);
374
+ }
375
+ /**
376
+ * Update workflow state in .n8n-state.json
377
+ * Only this component writes to the state file
378
+ */
379
+ async updateWorkflowState(id, hash) {
380
+ const state = this.loadState();
381
+ state.workflows[id] = {
382
+ lastSyncedHash: hash,
383
+ lastSyncedAt: new Date().toISOString()
384
+ };
385
+ this.saveState(state);
386
+ }
387
+ /**
388
+ * Remove workflow from state file
389
+ * Called after deletion confirmation
390
+ */
391
+ async removeWorkflowState(id) {
392
+ const state = this.loadState();
393
+ delete state.workflows[id];
394
+ this.saveState(state);
395
+ // Clean up internal tracking
396
+ const filename = this.idToFileMap.get(id);
397
+ if (filename) {
398
+ this.fileToIdMap.delete(filename);
399
+ }
400
+ this.idToFileMap.delete(id);
401
+ this.remoteHashes.delete(id);
402
+ this.remoteTimestamps.delete(id);
403
+ }
404
+ /**
405
+ * Load state from .n8n-state.json
406
+ */
407
+ loadState() {
408
+ if (fs.existsSync(this.stateFilePath)) {
409
+ try {
410
+ const data = JSON.parse(fs.readFileSync(this.stateFilePath, 'utf-8'));
411
+ if (!data.workflows) {
412
+ data.workflows = {};
413
+ }
414
+ return data;
415
+ }
416
+ catch (e) {
417
+ console.warn('Could not read state file, using empty state');
418
+ }
419
+ }
420
+ return { workflows: {} };
421
+ }
422
+ /**
423
+ * Save state to .n8n-state.json
424
+ */
425
+ saveState(state) {
426
+ fs.writeFileSync(this.stateFilePath, JSON.stringify(state, null, 2));
427
+ }
428
+ /**
429
+ * Compute canonical hash for content
430
+ */
431
+ computeHash(content) {
432
+ return HashUtils.computeHash(content);
433
+ }
434
+ broadcastStatus(filename, workflowId) {
435
+ if (this.isInitializing)
436
+ return;
437
+ const status = this.calculateStatus(filename, workflowId);
438
+ const key = workflowId || filename;
439
+ const lastStatus = this.lastKnownStatuses.get(key);
440
+ if (status !== lastStatus) {
441
+ this.lastKnownStatuses.set(key, status);
442
+ this.emit('statusChange', {
443
+ filename,
444
+ workflowId,
445
+ status
446
+ });
447
+ }
448
+ }
449
+ calculateStatus(filename, workflowId) {
450
+ if (!workflowId)
451
+ workflowId = this.fileToIdMap.get(filename);
452
+ const localHash = this.localHashes.get(filename);
453
+ const remoteHash = workflowId ? this.remoteHashes.get(workflowId) : undefined;
454
+ // If we are disconnected and don't have a remote hash, don't claim it's deleted
455
+ if (!this.isConnected && !remoteHash && workflowId) {
456
+ return WorkflowSyncStatus.IN_SYNC; // Treat as in-sync or unknown to avoid "deleted" panic
457
+ }
458
+ // Get base state
459
+ const state = this.loadState();
460
+ const baseState = workflowId ? state.workflows[workflowId] : undefined;
461
+ const lastSyncedHash = baseState?.lastSyncedHash;
462
+ // Implementation of 4.2 Status Logic Matrix from SPECS/REFACTO_CORE.md
463
+ if (localHash && !lastSyncedHash && !remoteHash)
464
+ return WorkflowSyncStatus.EXIST_ONLY_LOCALLY;
465
+ if (remoteHash && !lastSyncedHash && !localHash)
466
+ return WorkflowSyncStatus.EXIST_ONLY_REMOTELY;
467
+ if (localHash && remoteHash && localHash === remoteHash)
468
+ return WorkflowSyncStatus.IN_SYNC;
469
+ if (lastSyncedHash) {
470
+ // Check deletions first (they take precedence over modifications)
471
+ if (!localHash && remoteHash === lastSyncedHash)
472
+ return WorkflowSyncStatus.DELETED_LOCALLY;
473
+ if (!remoteHash && localHash === lastSyncedHash)
474
+ return WorkflowSyncStatus.DELETED_REMOTELY;
475
+ // Then check modifications
476
+ const localModified = localHash !== lastSyncedHash;
477
+ const remoteModified = remoteHash && remoteHash !== lastSyncedHash;
478
+ if (localModified && remoteModified)
479
+ return WorkflowSyncStatus.CONFLICT;
480
+ if (localModified && remoteHash === lastSyncedHash)
481
+ return WorkflowSyncStatus.MODIFIED_LOCALLY;
482
+ if (remoteModified && localHash === lastSyncedHash)
483
+ return WorkflowSyncStatus.MODIFIED_REMOTELY;
484
+ }
485
+ // Fallback for edge cases
486
+ return WorkflowSyncStatus.CONFLICT;
487
+ }
488
+ shouldIgnore(wf) {
489
+ if (!this.syncInactive && !wf.active)
490
+ return true;
491
+ if (wf.tags) {
492
+ const hasIgnoredTag = wf.tags.some(t => this.ignoredTags.includes(t.name.toLowerCase()));
493
+ if (hasIgnoredTag)
494
+ return true;
495
+ }
496
+ return false;
497
+ }
498
+ safeName(name) {
499
+ return name.replace(/[\/\\:]/g, '_').replace(/\s+/g, ' ').trim();
500
+ }
501
+ readJsonFile(filePath) {
502
+ try {
503
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
504
+ }
505
+ catch {
506
+ return null;
507
+ }
508
+ }
509
+ getFileToIdMap() {
510
+ return this.fileToIdMap;
511
+ }
512
+ getStatusMatrix() {
513
+ const results = new Map();
514
+ const state = this.loadState();
515
+ // 1. Process all local files
516
+ for (const [filename, hash] of this.localHashes.entries()) {
517
+ const workflowId = this.fileToIdMap.get(filename);
518
+ const status = this.calculateStatus(filename, workflowId);
519
+ results.set(filename, {
520
+ id: workflowId || '',
521
+ name: filename.replace('.json', ''),
522
+ filename: filename,
523
+ status: status,
524
+ active: true
525
+ });
526
+ }
527
+ // 2. Process all remote workflows not yet in results
528
+ for (const [workflowId, remoteHash] of this.remoteHashes.entries()) {
529
+ const filename = this.idToFileMap.get(workflowId) || `${workflowId}.json`;
530
+ if (!results.has(filename)) {
531
+ const status = this.calculateStatus(filename, workflowId);
532
+ results.set(filename, {
533
+ id: workflowId,
534
+ name: filename.replace('.json', ''),
535
+ filename: filename,
536
+ status: status,
537
+ active: true
538
+ });
539
+ }
540
+ }
541
+ // 3. Process tracked but deleted workflows
542
+ for (const id of Object.keys(state.workflows)) {
543
+ const filename = this.idToFileMap.get(id) || `${id}.json`;
544
+ if (!results.has(filename)) {
545
+ const status = this.calculateStatus(filename, id);
546
+ results.set(filename, {
547
+ id,
548
+ name: filename.replace('.json', ''),
549
+ filename,
550
+ status,
551
+ active: true
552
+ });
553
+ }
554
+ }
555
+ return Array.from(results.values()).sort((a, b) => a.name.localeCompare(b.name));
556
+ }
557
+ /**
558
+ * Get last synced hash for a workflow
559
+ */
560
+ getLastSyncedHash(workflowId) {
561
+ const state = this.loadState();
562
+ return state.workflows[workflowId]?.lastSyncedHash;
563
+ }
564
+ /**
565
+ * Update remote hash cache (for SyncEngine use)
566
+ * @internal
567
+ */
568
+ setRemoteHash(workflowId, hash) {
569
+ this.remoteHashes.set(workflowId, hash);
570
+ }
571
+ /**
572
+ * Get all tracked workflow IDs
573
+ */
574
+ getTrackedWorkflowIds() {
575
+ const state = this.loadState();
576
+ return Object.keys(state.workflows);
577
+ }
578
+ /**
579
+ * Update workflow ID in state (when a workflow is re-created with a new ID)
580
+ */
581
+ async updateWorkflowId(oldId, newId) {
582
+ const state = this.loadState();
583
+ // Migrate state from old ID to new ID
584
+ if (state.workflows[oldId]) {
585
+ state.workflows[newId] = state.workflows[oldId];
586
+ delete state.workflows[oldId];
587
+ this.saveState(state);
588
+ }
589
+ // Update internal mappings
590
+ const filename = this.idToFileMap.get(oldId);
591
+ if (filename) {
592
+ this.idToFileMap.delete(oldId);
593
+ this.idToFileMap.set(newId, filename);
594
+ this.fileToIdMap.set(filename, newId);
595
+ }
596
+ // Update hash maps
597
+ const remoteHash = this.remoteHashes.get(oldId);
598
+ if (remoteHash) {
599
+ this.remoteHashes.delete(oldId);
600
+ this.remoteHashes.set(newId, remoteHash);
601
+ }
602
+ const timestamp = this.remoteTimestamps.get(oldId);
603
+ if (timestamp) {
604
+ this.remoteTimestamps.delete(oldId);
605
+ this.remoteTimestamps.set(newId, timestamp);
606
+ }
607
+ }
608
+ }
609
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/services/watcher.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,5 @@
1
1
  import { IWorkflow } from '../types.js';
2
2
  export declare class WorkflowSanitizer {
3
- /**
4
- * Recursively sorts object keys to ensure deterministic JSON output.
5
- */
6
- private static sortKeys;
7
3
  /**
8
4
  * Prepares a workflow JSON for storage on disk (GIT).
9
5
  * Removes dynamic IDs, execution URLs, and standardizes key order.
@@ -12,6 +8,15 @@ export declare class WorkflowSanitizer {
12
8
  /**
13
9
  * Prepares a local workflow JSON for pushing to n8n API.
14
10
  * Removes read-only fields or fields that shouldn't be overwritten blindly (like tags if needed).
11
+ *
12
+ * n8n API v1 PUT /workflows/{id} expects a very specific schema.
13
+ * Based on n8n 2.2.6 API documentation, the allowed fields are:
14
+ * - name (string, required)
15
+ * - nodes (array, required)
16
+ * - connections (object, required)
17
+ * - settings (object, optional but with strict schema)
18
+ * - staticData (object, optional)
19
+ * - triggerCount (number, optional)
15
20
  */
16
21
  static cleanForPush(workflow: Partial<IWorkflow>): Partial<IWorkflow>;
17
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-sanitizer.d.ts","sourceRoot":"","sources":["../../src/services/workflow-sanitizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,qBAAa,iBAAiB;IAC1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;IAcvB;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IA6B/D;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;CAgCxE"}
1
+ {"version":3,"file":"workflow-sanitizer.d.ts","sourceRoot":"","sources":["../../src/services/workflow-sanitizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,qBAAa,iBAAiB;IAC1B;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAwD/D;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;CAoCxE"}