n8n-nodes-onedrive-business 1.1.2 → 1.1.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.
|
@@ -358,9 +358,9 @@ class OneDriveBusinessTrigger {
|
|
|
358
358
|
OneDriveBusinessTrigger.instances.set(nodeId, instance);
|
|
359
359
|
}
|
|
360
360
|
// Create delta processor
|
|
361
|
-
const deltaProcessor = new DeltaProcessor_1.DeltaProcessor(graphClient, instance.stateStore, drivePath);
|
|
361
|
+
const deltaProcessor = new DeltaProcessor_1.DeltaProcessor(graphClient, instance.stateStore, drivePath, watchPath);
|
|
362
362
|
// Process delta query
|
|
363
|
-
const triggerEvents = await deltaProcessor.processDeltaQuery(eventFilter
|
|
363
|
+
const triggerEvents = await deltaProcessor.processDeltaQuery(eventFilter);
|
|
364
364
|
// Clean up old versions periodically
|
|
365
365
|
const state = instance.stateStore.getState();
|
|
366
366
|
const processedCount = Object.keys(state.processedVersions).length;
|
|
@@ -36,21 +36,16 @@ export declare class DeltaProcessor {
|
|
|
36
36
|
private graphClient;
|
|
37
37
|
private stateStore;
|
|
38
38
|
private drivePath;
|
|
39
|
+
private watchPath?;
|
|
39
40
|
private stabilityTracker;
|
|
40
41
|
private readonly STABILITY_WINDOW_MS;
|
|
41
|
-
constructor(graphClient: GraphClient, stateStore: StateStore, drivePath: string);
|
|
42
|
+
constructor(graphClient: GraphClient, stateStore: StateStore, drivePath: string, watchPath?: string);
|
|
42
43
|
/**
|
|
43
44
|
* Process delta query and return triggerable events
|
|
44
45
|
*
|
|
45
46
|
* This is the main entry point called by the trigger node
|
|
46
47
|
*/
|
|
47
|
-
|
|
48
|
-
* Process delta query and return triggerable events
|
|
49
|
-
*
|
|
50
|
-
* This is the main entry point called by the trigger node
|
|
51
|
-
*/
|
|
52
|
-
processDeltaQuery(eventFilter: Set<string>, // e.g., ['file.created', 'file.updated']
|
|
53
|
-
watchPath?: string): Promise<TriggerEvent[]>;
|
|
48
|
+
processDeltaQuery(eventFilter: Set<string>): Promise<TriggerEvent[]>;
|
|
54
49
|
/**
|
|
55
50
|
* Fetch all pages from delta query
|
|
56
51
|
* Handles @odata.nextLink pagination and stores @odata.deltaLink
|
|
@@ -61,10 +56,6 @@ export declare class DeltaProcessor {
|
|
|
61
56
|
* Returns a TriggerEvent if the item should trigger a workflow
|
|
62
57
|
*/
|
|
63
58
|
private processItem;
|
|
64
|
-
/**
|
|
65
|
-
* Check if item is within the watched path
|
|
66
|
-
*/
|
|
67
|
-
private isItemInScope;
|
|
68
59
|
/**
|
|
69
60
|
* Classify event as created vs updated
|
|
70
61
|
*
|
|
@@ -34,7 +34,7 @@ const helpers_1 = require("./helpers");
|
|
|
34
34
|
* Without this processor, ONE file upload would trigger FOUR workflow executions.
|
|
35
35
|
*/
|
|
36
36
|
class DeltaProcessor {
|
|
37
|
-
constructor(graphClient, stateStore, drivePath) {
|
|
37
|
+
constructor(graphClient, stateStore, drivePath, watchPath) {
|
|
38
38
|
// Stability tracking for files currently being uploaded
|
|
39
39
|
this.stabilityTracker = new Map();
|
|
40
40
|
// Stability window: wait 15 seconds after last modification
|
|
@@ -42,19 +42,15 @@ class DeltaProcessor {
|
|
|
42
42
|
this.graphClient = graphClient;
|
|
43
43
|
this.stateStore = stateStore;
|
|
44
44
|
this.drivePath = drivePath;
|
|
45
|
+
this.watchPath = watchPath;
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* Process delta query and return triggerable events
|
|
48
49
|
*
|
|
49
50
|
* This is the main entry point called by the trigger node
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
* This is the main entry point called by the trigger node
|
|
55
|
-
*/
|
|
56
|
-
async processDeltaQuery(eventFilter, // e.g., ['file.created', 'file.updated']
|
|
57
|
-
watchPath) {
|
|
52
|
+
async processDeltaQuery(eventFilter // e.g., ['file.created', 'file.updated']
|
|
53
|
+
) {
|
|
58
54
|
const events = [];
|
|
59
55
|
try {
|
|
60
56
|
// Get current state
|
|
@@ -69,13 +65,28 @@ class DeltaProcessor {
|
|
|
69
65
|
}
|
|
70
66
|
else {
|
|
71
67
|
// Initial delta query
|
|
72
|
-
|
|
68
|
+
if (this.watchPath && this.watchPath !== '' && this.watchPath !== '/') {
|
|
69
|
+
// Scope to specific folder
|
|
70
|
+
let path = this.watchPath;
|
|
71
|
+
if (!path.startsWith('/')) {
|
|
72
|
+
path = '/' + path;
|
|
73
|
+
}
|
|
74
|
+
// Syntax: /drive/root:/path/to/folder:/delta
|
|
75
|
+
// Note the colons wrapping the path
|
|
76
|
+
deltaEndpoint = `${this.drivePath}/root:${encodeURIComponent(path)}:/delta`;
|
|
77
|
+
console.log(`[DeltaProcessor] Initializing Scoped Delta Query: ${deltaEndpoint}`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// Browse entire drive
|
|
81
|
+
deltaEndpoint = `${this.drivePath}/root/delta`;
|
|
82
|
+
console.log(`[DeltaProcessor] Initializing Root Delta Query`);
|
|
83
|
+
}
|
|
73
84
|
}
|
|
74
85
|
// Fetch delta changes (handle pagination)
|
|
75
86
|
const items = await this.fetchAllDeltaPages(deltaEndpoint);
|
|
76
87
|
// Process each item
|
|
77
88
|
for (const item of items) {
|
|
78
|
-
const event = await this.processItem(item, eventFilter
|
|
89
|
+
const event = await this.processItem(item, eventFilter);
|
|
79
90
|
if (event) {
|
|
80
91
|
events.push(event);
|
|
81
92
|
}
|
|
@@ -95,6 +106,8 @@ class DeltaProcessor {
|
|
|
95
106
|
const allItems = [];
|
|
96
107
|
let currentEndpoint = initialEndpoint;
|
|
97
108
|
while (currentEndpoint) {
|
|
109
|
+
// Log for debugging
|
|
110
|
+
console.log(`[DeltaProcessor] Fetching: ${currentEndpoint}`);
|
|
98
111
|
const response = await this.graphClient.get(currentEndpoint);
|
|
99
112
|
allItems.push(...response.value);
|
|
100
113
|
// Check for next page
|
|
@@ -119,19 +132,18 @@ class DeltaProcessor {
|
|
|
119
132
|
* Process a single delta item
|
|
120
133
|
* Returns a TriggerEvent if the item should trigger a workflow
|
|
121
134
|
*/
|
|
122
|
-
async processItem(item, eventFilter
|
|
135
|
+
async processItem(item, eventFilter) {
|
|
123
136
|
// Skip deleted items (unless specifically requested)
|
|
124
137
|
if (item.deleted) {
|
|
125
138
|
return null;
|
|
126
139
|
}
|
|
127
|
-
// Skip root folder
|
|
140
|
+
// Skip root folder (the folder itself, not its children)
|
|
128
141
|
if (!item.parentReference) {
|
|
129
142
|
return null;
|
|
130
143
|
}
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
144
|
+
// Note: We don't need manual scope checking (isItemInScope) anymore
|
|
145
|
+
// because the Delta Query itself is scoped to the target folder.
|
|
146
|
+
// Any item returned here IS in the scope.
|
|
135
147
|
// Determine event type
|
|
136
148
|
const eventType = this.classifyEvent(item);
|
|
137
149
|
// Check if this event type is enabled
|
|
@@ -163,42 +175,6 @@ class DeltaProcessor {
|
|
|
163
175
|
timestamp: new Date().toISOString(),
|
|
164
176
|
};
|
|
165
177
|
}
|
|
166
|
-
/**
|
|
167
|
-
* Check if item is within the watched path
|
|
168
|
-
*/
|
|
169
|
-
isItemInScope(item, watchPath) {
|
|
170
|
-
if (!item.parentReference || !item.parentReference.path) {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
// Extract relative path from parentReference.path
|
|
174
|
-
// Format: /drives/{drive-id}/root:/path/to/folder
|
|
175
|
-
const parts = item.parentReference.path.split('root:');
|
|
176
|
-
if (parts.length < 2) {
|
|
177
|
-
// Item is in root
|
|
178
|
-
// If watchPath is /, then it's a match. Otherwise no.
|
|
179
|
-
return watchPath === '/' || watchPath === '';
|
|
180
|
-
}
|
|
181
|
-
let relativePath = parts[1]; // /path/to/folder
|
|
182
|
-
// Ensure paths start with / for consistent comparison
|
|
183
|
-
if (!relativePath.startsWith('/')) {
|
|
184
|
-
relativePath = '/' + relativePath;
|
|
185
|
-
}
|
|
186
|
-
// Ensure watchPath starts with /
|
|
187
|
-
let normalizedWatchPath = watchPath;
|
|
188
|
-
if (!normalizedWatchPath.startsWith('/')) {
|
|
189
|
-
normalizedWatchPath = '/' + normalizedWatchPath;
|
|
190
|
-
}
|
|
191
|
-
// Check if relative path matches or is a subfolder
|
|
192
|
-
// 1. Exact match: relativePath === normalizedWatchPath
|
|
193
|
-
// 2. Subfolder: relativePath startsWith normalizedWatchPath + '/'
|
|
194
|
-
if (relativePath === normalizedWatchPath) {
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
if (relativePath.startsWith(normalizedWatchPath + '/')) {
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
178
|
/**
|
|
203
179
|
* Classify event as created vs updated
|
|
204
180
|
*
|