@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.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/services/hash-utils.d.ts +22 -0
- package/dist/services/hash-utils.d.ts.map +1 -0
- package/dist/services/hash-utils.js +31 -0
- package/dist/services/hash-utils.js.map +1 -0
- package/dist/services/n8n-api-client.d.ts.map +1 -1
- package/dist/services/n8n-api-client.js +44 -50
- package/dist/services/n8n-api-client.js.map +1 -1
- package/dist/services/resolution-manager.d.ts +73 -0
- package/dist/services/resolution-manager.d.ts.map +1 -0
- package/dist/services/resolution-manager.js +149 -0
- package/dist/services/resolution-manager.js.map +1 -0
- package/dist/services/state-manager.d.ts +18 -17
- package/dist/services/state-manager.d.ts.map +1 -1
- package/dist/services/state-manager.js +22 -53
- package/dist/services/state-manager.js.map +1 -1
- package/dist/services/sync-engine.d.ts +57 -0
- package/dist/services/sync-engine.d.ts.map +1 -0
- package/dist/services/sync-engine.js +301 -0
- package/dist/services/sync-engine.js.map +1 -0
- package/dist/services/sync-manager.d.ts +19 -83
- package/dist/services/sync-manager.d.ts.map +1 -1
- package/dist/services/sync-manager.js +208 -620
- package/dist/services/sync-manager.js.map +1 -1
- package/dist/services/watcher.d.ts +121 -0
- package/dist/services/watcher.d.ts.map +1 -0
- package/dist/services/watcher.js +609 -0
- package/dist/services/watcher.js.map +1 -0
- package/dist/services/workflow-sanitizer.d.ts +9 -4
- package/dist/services/workflow-sanitizer.d.ts.map +1 -1
- package/dist/services/workflow-sanitizer.js +55 -35
- package/dist/services/workflow-sanitizer.js.map +1 -1
- package/dist/types.d.ts +10 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -5
- package/dist/types.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export * from './types.js';
|
|
|
2
2
|
export * from './services/n8n-api-client.js';
|
|
3
3
|
export * from './services/workflow-sanitizer.js';
|
|
4
4
|
export * from './services/sync-manager.js';
|
|
5
|
+
export * from './services/sync-engine.js';
|
|
6
|
+
export * from './services/watcher.js';
|
|
7
|
+
export * from './services/resolution-manager.js';
|
|
5
8
|
export * from './services/state-manager.js';
|
|
6
9
|
export * from './services/schema-generator.js';
|
|
7
10
|
export * from './services/sync-manager.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAI/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAI/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@ export * from './types.js';
|
|
|
2
2
|
export * from './services/n8n-api-client.js';
|
|
3
3
|
export * from './services/workflow-sanitizer.js';
|
|
4
4
|
export * from './services/sync-manager.js';
|
|
5
|
+
export * from './services/sync-engine.js';
|
|
6
|
+
export * from './services/watcher.js';
|
|
7
|
+
export * from './services/resolution-manager.js';
|
|
5
8
|
export * from './services/state-manager.js';
|
|
6
9
|
export * from './services/schema-generator.js';
|
|
7
10
|
export * from './services/sync-manager.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAI/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAI/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash Utilities for canonical hashing
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent SHA-256 hashing of JSON content with stable stringification.
|
|
5
|
+
* Used by all components to ensure hash consistency.
|
|
6
|
+
*/
|
|
7
|
+
export declare class HashUtils {
|
|
8
|
+
/**
|
|
9
|
+
* Computes a stable, canonical hash for any object (usually a workflow).
|
|
10
|
+
* Non-functional metadata should be removed before calling this.
|
|
11
|
+
*/
|
|
12
|
+
static computeHash(content: any): string;
|
|
13
|
+
/**
|
|
14
|
+
* Compares two objects by computing their canonical hashes
|
|
15
|
+
*/
|
|
16
|
+
static areEqual(obj1: any, obj2: any): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Short hash for display purposes
|
|
19
|
+
*/
|
|
20
|
+
static shortHash(hash: string, length?: number): string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=hash-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-utils.d.ts","sourceRoot":"","sources":["../../src/services/hash-utils.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,SAAS;IAClB;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM;IAKxC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO;IAI9C;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM;CAG7D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import stringify from 'json-stable-stringify';
|
|
3
|
+
/**
|
|
4
|
+
* Hash Utilities for canonical hashing
|
|
5
|
+
*
|
|
6
|
+
* Provides consistent SHA-256 hashing of JSON content with stable stringification.
|
|
7
|
+
* Used by all components to ensure hash consistency.
|
|
8
|
+
*/
|
|
9
|
+
export class HashUtils {
|
|
10
|
+
/**
|
|
11
|
+
* Computes a stable, canonical hash for any object (usually a workflow).
|
|
12
|
+
* Non-functional metadata should be removed before calling this.
|
|
13
|
+
*/
|
|
14
|
+
static computeHash(content) {
|
|
15
|
+
const canonicalString = stringify(content) || '';
|
|
16
|
+
return crypto.createHash('sha256').update(canonicalString).digest('hex');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Compares two objects by computing their canonical hashes
|
|
20
|
+
*/
|
|
21
|
+
static areEqual(obj1, obj2) {
|
|
22
|
+
return this.computeHash(obj1) === this.computeHash(obj2);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Short hash for display purposes
|
|
26
|
+
*/
|
|
27
|
+
static shortHash(hash, length = 8) {
|
|
28
|
+
return hash.substring(0, length);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=hash-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-utils.js","sourceRoot":"","sources":["../../src/services/hash-utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,SAAS,MAAM,uBAAuB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IAClB;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAY;QAC3B,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7E,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAS,EAAE,IAAS;QAChC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAY,EAAE,SAAiB,CAAC;QAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"n8n-api-client.d.ts","sourceRoot":"","sources":["../../src/services/n8n-api-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzD,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAgB;gBAElB,WAAW,EAAE,eAAe;IAoBlC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAUlC,cAAc,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"n8n-api-client.d.ts","sourceRoot":"","sources":["../../src/services/n8n-api-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzD,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAgB;gBAElB,WAAW,EAAE,eAAe;IAoBlC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAUlC,cAAc,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAAE,GAAG,IAAI,CAAC;IA2CvG,eAAe,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAWvC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAclD,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAK/D,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAoB3E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5C,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAS/D,SAAS,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAsCzC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;CAUvC"}
|
|
@@ -31,59 +31,48 @@ export class N8nApiClient {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
async getCurrentUser() {
|
|
34
|
+
// Try /me first (modern n8n)
|
|
34
35
|
try {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
lastName: res.data.lastName
|
|
45
|
-
};
|
|
46
|
-
}
|
|
36
|
+
const res = await this.client.get('/api/v1/users/me');
|
|
37
|
+
console.debug('[N8nApiClient] getCurrentUser: Successfully retrieved user from /me endpoint');
|
|
38
|
+
if (res.data && res.data.id) {
|
|
39
|
+
return {
|
|
40
|
+
id: res.data.id,
|
|
41
|
+
email: res.data.email,
|
|
42
|
+
firstName: res.data.firstName,
|
|
43
|
+
lastName: res.data.lastName
|
|
44
|
+
};
|
|
47
45
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
console.debug('[N8nApiClient] getCurrentUser: No users found in response');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
console.debug('[N8nApiClient] getCurrentUser: /api/v1/users endpoint failed:', error.message);
|
|
76
|
-
if (error.response) {
|
|
77
|
-
console.debug('[N8nApiClient] getCurrentUser: Response status:', error.response.status);
|
|
78
|
-
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.debug('[N8nApiClient] getCurrentUser: /me endpoint failed:', error.message);
|
|
49
|
+
// If it's a connection error, throw immediately
|
|
50
|
+
if (!error.response)
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
// Fallback: get all users and take the first one (assuming the API key belongs to an admin or the only user)
|
|
54
|
+
console.debug('[N8nApiClient] getCurrentUser: Trying /api/v1/users endpoint');
|
|
55
|
+
try {
|
|
56
|
+
const res = await this.client.get('/api/v1/users');
|
|
57
|
+
if (res.data && res.data.data && res.data.data.length > 0) {
|
|
58
|
+
console.debug('[N8nApiClient] getCurrentUser: Found', res.data.data.length, 'users');
|
|
59
|
+
const user = res.data.data[0];
|
|
60
|
+
return {
|
|
61
|
+
id: user.id,
|
|
62
|
+
email: user.email,
|
|
63
|
+
firstName: user.firstName,
|
|
64
|
+
lastName: user.lastName
|
|
65
|
+
};
|
|
79
66
|
}
|
|
80
|
-
console.debug('[N8nApiClient] getCurrentUser: All attempts failed, returning null');
|
|
81
|
-
return null;
|
|
82
67
|
}
|
|
83
68
|
catch (error) {
|
|
84
|
-
console.debug('[N8nApiClient] getCurrentUser:
|
|
85
|
-
|
|
69
|
+
console.debug('[N8nApiClient] getCurrentUser: /api/v1/users endpoint failed:', error.message);
|
|
70
|
+
// If it's a connection error, throw immediately
|
|
71
|
+
if (!error.response)
|
|
72
|
+
throw error;
|
|
86
73
|
}
|
|
74
|
+
console.debug('[N8nApiClient] getCurrentUser: All attempts failed, returning null');
|
|
75
|
+
return null;
|
|
87
76
|
}
|
|
88
77
|
async getAllWorkflows() {
|
|
89
78
|
try {
|
|
@@ -91,8 +80,9 @@ export class N8nApiClient {
|
|
|
91
80
|
return res.data.data;
|
|
92
81
|
}
|
|
93
82
|
catch (error) {
|
|
94
|
-
console.error('Failed to get workflows:', error);
|
|
95
|
-
|
|
83
|
+
console.error('Failed to get workflows:', error.message);
|
|
84
|
+
// Re-throw so the caller (Watcher) can distinguish between "no workflows" and "connection error"
|
|
85
|
+
throw error;
|
|
96
86
|
}
|
|
97
87
|
}
|
|
98
88
|
async getWorkflow(id) {
|
|
@@ -102,7 +92,11 @@ export class N8nApiClient {
|
|
|
102
92
|
}
|
|
103
93
|
catch (error) {
|
|
104
94
|
// 404 is expected if workflow deleted remotely
|
|
105
|
-
|
|
95
|
+
if (error.response && error.response.status === 404) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// Re-throw other errors (connection, 500, etc.)
|
|
99
|
+
throw error;
|
|
106
100
|
}
|
|
107
101
|
}
|
|
108
102
|
async createWorkflow(payload) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"n8n-api-client.js","sourceRoot":"","sources":["../../src/services/n8n-api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,OAAO,YAAY;IACb,MAAM,CAAgB;IAE9B,YAAY,WAA4B;QACpC,IAAI,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;QAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE;gBACL,eAAe,EAAE,WAAW,CAAC,MAAM;gBACnC,cAAc,EAAE,kBAAkB;gBAClC,YAAY,EAAE,aAAa;aAC9B;YACD,kFAAkF;YAClF,UAAU,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC;gBACxB,kBAAkB,EAAE,KAAK;aAC5B,CAAC;SACL,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,cAAc;QAChB,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,+BAA+B;YACvE,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc;QAChB,
|
|
1
|
+
{"version":3,"file":"n8n-api-client.js","sourceRoot":"","sources":["../../src/services/n8n-api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SyncEngine } from './sync-engine.js';
|
|
2
|
+
import { Watcher } from './watcher.js';
|
|
3
|
+
import { WorkflowSyncStatus } from '../types.js';
|
|
4
|
+
import { N8nApiClient } from './n8n-api-client.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolution & Validation Manager
|
|
7
|
+
*
|
|
8
|
+
* Responsibilities:
|
|
9
|
+
* 1. Conflict Resolution (6.1 from spec)
|
|
10
|
+
* 2. Deletion Validation (6.2 from spec)
|
|
11
|
+
*
|
|
12
|
+
* Bridges user intent with Sync Engine operations
|
|
13
|
+
*/
|
|
14
|
+
export declare class ResolutionManager {
|
|
15
|
+
private syncEngine;
|
|
16
|
+
private watcher;
|
|
17
|
+
private client;
|
|
18
|
+
private directory;
|
|
19
|
+
constructor(syncEngine: SyncEngine, watcher: Watcher, client: N8nApiClient);
|
|
20
|
+
/**
|
|
21
|
+
* 6.1 Conflict Resolution - KEEP LOCAL
|
|
22
|
+
*
|
|
23
|
+
* Action: Force PUSH (Overwrite Remote with Local)
|
|
24
|
+
* Commit: Update lastSyncedHash = LocalHash. Status becomes IN_SYNC.
|
|
25
|
+
*/
|
|
26
|
+
keepLocal(workflowId: string, filename: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* 6.1 Conflict Resolution - KEEP REMOTE
|
|
29
|
+
*
|
|
30
|
+
* Action: Force PULL (Overwrite Local with Remote)
|
|
31
|
+
* Commit: Update lastSyncedHash = RemoteHash. Status becomes IN_SYNC.
|
|
32
|
+
*/
|
|
33
|
+
keepRemote(workflowId: string, filename: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* 6.1 Conflict Resolution - SHOW DIFF
|
|
36
|
+
*
|
|
37
|
+
* Opens diff editor (implementation depends on UI layer)
|
|
38
|
+
* Returns diff data for UI to display
|
|
39
|
+
*/
|
|
40
|
+
showDiff(workflowId: string, filename: string): Promise<{
|
|
41
|
+
localContent: any;
|
|
42
|
+
remoteContent: any;
|
|
43
|
+
localHash: string;
|
|
44
|
+
remoteHash: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* 6.2 Deletion Validation - CONFIRM DELETION
|
|
48
|
+
*
|
|
49
|
+
* Case Deleted Locally: Send DELETE to API -> Remove from state
|
|
50
|
+
* Case Deleted Remotely: Move local file to _archive/ -> Remove from state
|
|
51
|
+
*/
|
|
52
|
+
confirmDeletion(workflowId: string, filename: string, deletionType: 'local' | 'remote'): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* 6.2 Deletion Validation - RESTORE WORKFLOW
|
|
55
|
+
*
|
|
56
|
+
* Case Deleted Locally: Move file from _archive/ to workflows/
|
|
57
|
+
* Case Deleted Remotely: Force PUSH (Re-create on Remote)
|
|
58
|
+
*/
|
|
59
|
+
restoreWorkflow(workflowId: string, filename: string, deletionType: 'local' | 'remote'): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Get current status for a workflow
|
|
62
|
+
*/
|
|
63
|
+
getWorkflowStatus(workflowId: string, filename: string): Promise<{
|
|
64
|
+
status: WorkflowSyncStatus;
|
|
65
|
+
localExists: boolean;
|
|
66
|
+
remoteExists: boolean;
|
|
67
|
+
lastSyncedHash?: string;
|
|
68
|
+
localHash?: string;
|
|
69
|
+
remoteHash?: string;
|
|
70
|
+
}>;
|
|
71
|
+
private readJsonFile;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=resolution-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution-manager.d.ts","sourceRoot":"","sources":["../../src/services/resolution-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAEd,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY;IAQ1E;;;;;OAKG;IACU,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM7E;;;;;OAKG;IACU,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5E;;;;;OAKG;IACU,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACjE,YAAY,EAAE,GAAG,CAAC;QAClB,aAAa,EAAE,GAAG,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;IA4BF;;;;;OAKG;IACU,eAAe,CACxB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,OAAO,GAAG,QAAQ,GACjC,OAAO,CAAC,IAAI,CAAC;IAchB;;;;;OAKG;IACU,eAAe,CACxB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,OAAO,GAAG,QAAQ,GACjC,OAAO,CAAC,MAAM,CAAC;IAgBlB;;OAEG;IACU,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1E,MAAM,EAAE,kBAAkB,CAAC;QAC3B,WAAW,EAAE,OAAO,CAAC;QACrB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAwBF,OAAO,CAAC,YAAY;CAOvB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { WorkflowSanitizer } from './workflow-sanitizer.js';
|
|
4
|
+
import { HashUtils } from './hash-utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolution & Validation Manager
|
|
7
|
+
*
|
|
8
|
+
* Responsibilities:
|
|
9
|
+
* 1. Conflict Resolution (6.1 from spec)
|
|
10
|
+
* 2. Deletion Validation (6.2 from spec)
|
|
11
|
+
*
|
|
12
|
+
* Bridges user intent with Sync Engine operations
|
|
13
|
+
*/
|
|
14
|
+
export class ResolutionManager {
|
|
15
|
+
syncEngine;
|
|
16
|
+
watcher;
|
|
17
|
+
client;
|
|
18
|
+
directory;
|
|
19
|
+
constructor(syncEngine, watcher, client) {
|
|
20
|
+
this.syncEngine = syncEngine;
|
|
21
|
+
this.watcher = watcher;
|
|
22
|
+
this.client = client;
|
|
23
|
+
// Get directory from sync engine (private access)
|
|
24
|
+
this.directory = syncEngine.directory;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 6.1 Conflict Resolution - KEEP LOCAL
|
|
28
|
+
*
|
|
29
|
+
* Action: Force PUSH (Overwrite Remote with Local)
|
|
30
|
+
* Commit: Update lastSyncedHash = LocalHash. Status becomes IN_SYNC.
|
|
31
|
+
*/
|
|
32
|
+
async keepLocal(workflowId, filename) {
|
|
33
|
+
const finalWorkflowId = await this.syncEngine.forcePush(workflowId, filename);
|
|
34
|
+
// Note: forcePush already calls watcher.finalizeSync
|
|
35
|
+
return finalWorkflowId;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 6.1 Conflict Resolution - KEEP REMOTE
|
|
39
|
+
*
|
|
40
|
+
* Action: Force PULL (Overwrite Local with Remote)
|
|
41
|
+
* Commit: Update lastSyncedHash = RemoteHash. Status becomes IN_SYNC.
|
|
42
|
+
*/
|
|
43
|
+
async keepRemote(workflowId, filename) {
|
|
44
|
+
await this.syncEngine.forcePull(workflowId, filename);
|
|
45
|
+
// Note: forcePull already calls watcher.finalizeSync
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 6.1 Conflict Resolution - SHOW DIFF
|
|
49
|
+
*
|
|
50
|
+
* Opens diff editor (implementation depends on UI layer)
|
|
51
|
+
* Returns diff data for UI to display
|
|
52
|
+
*/
|
|
53
|
+
async showDiff(workflowId, filename) {
|
|
54
|
+
// Get local content
|
|
55
|
+
const filePath = path.join(this.directory, filename);
|
|
56
|
+
const localContent = this.readJsonFile(filePath);
|
|
57
|
+
// Get remote content
|
|
58
|
+
const remoteContent = await this.client.getWorkflow(workflowId);
|
|
59
|
+
if (!localContent || !remoteContent) {
|
|
60
|
+
throw new Error('Cannot show diff: missing local or remote content');
|
|
61
|
+
}
|
|
62
|
+
// Clean for comparison
|
|
63
|
+
const cleanLocal = WorkflowSanitizer.cleanForStorage(localContent);
|
|
64
|
+
const cleanRemote = WorkflowSanitizer.cleanForStorage(remoteContent);
|
|
65
|
+
// Compute hashes
|
|
66
|
+
const localHash = HashUtils.computeHash(cleanLocal);
|
|
67
|
+
const remoteHash = HashUtils.computeHash(cleanRemote);
|
|
68
|
+
return {
|
|
69
|
+
localContent: cleanLocal,
|
|
70
|
+
remoteContent: cleanRemote,
|
|
71
|
+
localHash,
|
|
72
|
+
remoteHash
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 6.2 Deletion Validation - CONFIRM DELETION
|
|
77
|
+
*
|
|
78
|
+
* Case Deleted Locally: Send DELETE to API -> Remove from state
|
|
79
|
+
* Case Deleted Remotely: Move local file to _archive/ -> Remove from state
|
|
80
|
+
*/
|
|
81
|
+
async confirmDeletion(workflowId, filename, deletionType) {
|
|
82
|
+
if (deletionType === 'local') {
|
|
83
|
+
// Local file was deleted, confirm remote deletion
|
|
84
|
+
await this.syncEngine.deleteRemote(workflowId, filename);
|
|
85
|
+
// Remove from state
|
|
86
|
+
await this.watcher.removeWorkflowState(workflowId);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Remote workflow was deleted, confirm local archiving
|
|
90
|
+
await this.syncEngine.archive(filename);
|
|
91
|
+
// Remove from state
|
|
92
|
+
await this.watcher.removeWorkflowState(workflowId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 6.2 Deletion Validation - RESTORE WORKFLOW
|
|
97
|
+
*
|
|
98
|
+
* Case Deleted Locally: Move file from _archive/ to workflows/
|
|
99
|
+
* Case Deleted Remotely: Force PUSH (Re-create on Remote)
|
|
100
|
+
*/
|
|
101
|
+
async restoreWorkflow(workflowId, filename, deletionType) {
|
|
102
|
+
if (deletionType === 'local') {
|
|
103
|
+
// Restore from archive
|
|
104
|
+
const restored = await this.syncEngine.restoreFromArchive(filename);
|
|
105
|
+
if (!restored) {
|
|
106
|
+
throw new Error(`Cannot restore ${filename}: not found in archive`);
|
|
107
|
+
}
|
|
108
|
+
// Watcher will detect file addition and update status
|
|
109
|
+
return workflowId;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Re-create on remote (force push)
|
|
113
|
+
const finalWorkflowId = await this.syncEngine.forcePush(workflowId, filename);
|
|
114
|
+
return finalWorkflowId;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get current status for a workflow
|
|
119
|
+
*/
|
|
120
|
+
async getWorkflowStatus(workflowId, filename) {
|
|
121
|
+
const status = this.watcher.calculateStatus(filename, workflowId);
|
|
122
|
+
const lastSyncedHash = this.watcher.getLastSyncedHash(workflowId);
|
|
123
|
+
// Get local hash
|
|
124
|
+
const filePath = path.join(this.directory, filename);
|
|
125
|
+
const localContent = this.readJsonFile(filePath);
|
|
126
|
+
const localHash = localContent ?
|
|
127
|
+
HashUtils.computeHash(WorkflowSanitizer.cleanForStorage(localContent)) :
|
|
128
|
+
undefined;
|
|
129
|
+
// Get remote hash from watcher cache
|
|
130
|
+
const remoteHash = this.watcher.remoteHashes?.get(workflowId);
|
|
131
|
+
return {
|
|
132
|
+
status,
|
|
133
|
+
localExists: !!localContent,
|
|
134
|
+
remoteExists: !!remoteHash,
|
|
135
|
+
lastSyncedHash,
|
|
136
|
+
localHash,
|
|
137
|
+
remoteHash
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
readJsonFile(filePath) {
|
|
141
|
+
try {
|
|
142
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=resolution-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution-manager.js","sourceRoot":"","sources":["../../src/services/resolution-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,38 +5,39 @@ export interface IWorkflowState {
|
|
|
5
5
|
export interface IInstanceState {
|
|
6
6
|
workflows: Record<string, IWorkflowState>;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Read-only State Manager
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities:
|
|
12
|
+
* 1. Read state from .n8n-state.json
|
|
13
|
+
* 2. Provide read-only access to workflow states
|
|
14
|
+
*
|
|
15
|
+
* Note: Write operations are handled exclusively by Watcher component
|
|
16
|
+
* to maintain single source of truth for state mutations.
|
|
17
|
+
*/
|
|
8
18
|
export declare class StateManager {
|
|
9
19
|
private stateFilePath;
|
|
10
20
|
constructor(directory: string);
|
|
11
|
-
private load;
|
|
12
|
-
private save;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
22
|
+
* Load state from disk (private method)
|
|
15
23
|
*/
|
|
16
|
-
|
|
24
|
+
private load;
|
|
17
25
|
/**
|
|
18
|
-
* Gets the last known state for a workflow.
|
|
26
|
+
* Gets the last known state (Base) for a workflow.
|
|
19
27
|
*/
|
|
20
28
|
getWorkflowState(id: string): IWorkflowState | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* Updates the last known state for a workflow.
|
|
23
|
-
*/
|
|
24
|
-
updateWorkflowState(id: string, workflow: any): void;
|
|
25
|
-
/**
|
|
26
|
-
* Removes a workflow from state.
|
|
27
|
-
*/
|
|
28
|
-
removeWorkflowState(id: string): void;
|
|
29
29
|
/**
|
|
30
30
|
* Gets all tracked workflow IDs.
|
|
31
31
|
*/
|
|
32
32
|
getTrackedWorkflowIds(): string[];
|
|
33
33
|
/**
|
|
34
|
-
* Checks if a
|
|
34
|
+
* Checks if a hash matches the last synced state.
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
isSynced(id: string, currentHash: string): boolean;
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* Get the entire state object (for Watcher's internal use)
|
|
39
|
+
* @internal
|
|
39
40
|
*/
|
|
40
|
-
|
|
41
|
+
getFullState(): IInstanceState;
|
|
41
42
|
}
|
|
42
43
|
//# sourceMappingURL=state-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../src/services/state-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../src/services/state-manager.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC7C;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,aAAa,CAAS;gBAElB,SAAS,EAAE,MAAM;IAI7B;;OAEG;IACH,OAAO,CAAC,IAAI;IAgBZ;;OAEG;IACH,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAKxD;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAKjC;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAMlD;;;OAGG;IACH,YAAY,IAAI,cAAc;CAGjC"}
|