@pipedream/sharepoint 0.8.0 → 0.8.2
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/actions/create-folder/create-folder.mjs +1 -1
- package/actions/create-item/create-item.mjs +1 -1
- package/actions/create-link/create-link.mjs +1 -1
- package/actions/create-list/create-list.mjs +1 -1
- package/actions/download-file/download-file.mjs +10 -16
- package/actions/download-files/download-files.mjs +1 -1
- package/actions/find-file-by-name/find-file-by-name.mjs +1 -1
- package/actions/find-files-with-metadata/find-files-with-metadata.mjs +1 -1
- package/actions/get-excel-table/get-excel-table.mjs +1 -1
- package/actions/get-file-by-id/get-file-by-id.mjs +1 -1
- package/actions/get-site/get-site.mjs +1 -1
- package/actions/list-files-in-folder/list-files-in-folder.mjs +1 -1
- package/actions/list-sites/list-sites.mjs +1 -1
- package/actions/retrieve-file-metadata/retrieve-file-metadata.mjs +1 -1
- package/actions/search-and-filter-files/search-and-filter-files.mjs +1 -1
- package/actions/search-files/search-files.mjs +1 -1
- package/actions/search-sites/search-sites.mjs +1 -1
- package/actions/update-item/update-item.mjs +1 -1
- package/actions/upload-file/upload-file.mjs +8 -3
- package/package.json +4 -4
- package/sharepoint.app.mjs +151 -387
- package/sources/new-file-created/new-file-created.mjs +1 -1
- package/sources/new-folder-created/new-folder-created.mjs +1 -1
- package/sources/new-list-item/new-list-item.mjs +1 -1
- package/sources/updated-file-instant/updated-file-instant.mjs +59 -13
- package/sources/updated-list-item/updated-list-item.mjs +1 -1
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-create-folder",
|
|
5
5
|
name: "Create Folder",
|
|
6
6
|
description: "Create a new folder in SharePoint. [See the documentation](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_post_children?view=odsp-graph-online)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.6",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-create-item",
|
|
5
5
|
name: "Create Item",
|
|
6
6
|
description: "Create a new item in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/listitem-create?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.12",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
key: "sharepoint-create-link",
|
|
6
6
|
name: "Create Link",
|
|
7
7
|
description: "Create a sharing link for a DriveItem. [See the documentation](https://docs.microsoft.com/en-us/graph/api/driveitem-createlink?view=graph-rest-1.0&tabs=http)",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.8",
|
|
9
9
|
type: "action",
|
|
10
10
|
annotations: {
|
|
11
11
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-create-list",
|
|
5
5
|
name: "Create List",
|
|
6
6
|
description: "Create a new list in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/list-create?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.12",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -8,7 +8,7 @@ export default {
|
|
|
8
8
|
key: "sharepoint-download-file",
|
|
9
9
|
name: "Download File",
|
|
10
10
|
description: "Download a Microsoft Sharepoint file to the /tmp directory. [See the documentation](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http)",
|
|
11
|
-
version: "0.0.
|
|
11
|
+
version: "0.0.13",
|
|
12
12
|
annotations: {
|
|
13
13
|
destructiveHint: false,
|
|
14
14
|
openWorldHint: true,
|
|
@@ -116,31 +116,25 @@ export default {
|
|
|
116
116
|
this.validateConversionFormat(originalExtension);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
let args = {
|
|
121
|
-
$,
|
|
119
|
+
const response = await this.sharepoint.getFile({
|
|
122
120
|
driveId: this.driveId,
|
|
123
121
|
fileId: this.fileId,
|
|
124
122
|
params: {
|
|
125
123
|
format: this.convertToFormat,
|
|
126
124
|
},
|
|
127
|
-
};
|
|
128
|
-
try {
|
|
129
|
-
response = await this.sharepoint.getFile({
|
|
130
|
-
...args,
|
|
131
|
-
responseType: "arraybuffer",
|
|
132
|
-
});
|
|
133
|
-
} catch {
|
|
134
|
-
// throw error without buffer encoding
|
|
135
|
-
await this.sharepoint.getFile(args);
|
|
136
|
-
}
|
|
125
|
+
});
|
|
137
126
|
|
|
138
|
-
const rawcontent = response.toString("base64");
|
|
139
|
-
const buffer = Buffer.from(rawcontent, "base64");
|
|
140
127
|
// Since the filepath is not returned as one of the standard keys (filePath
|
|
141
128
|
// or path), save the file to STASH_DIR, if defined, so it is synced at the
|
|
142
129
|
// end of execution.
|
|
143
130
|
const downloadedFilepath = `${process.env.STASH_DIR || "/tmp"}/${filename}`;
|
|
131
|
+
|
|
132
|
+
const chunks = [];
|
|
133
|
+
for await (const chunk of response) {
|
|
134
|
+
chunks.push(chunk);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const buffer = Buffer.concat(chunks);
|
|
144
138
|
fs.writeFileSync(downloadedFilepath, buffer);
|
|
145
139
|
|
|
146
140
|
const data = {
|
|
@@ -6,7 +6,7 @@ export default {
|
|
|
6
6
|
key: "sharepoint-download-files",
|
|
7
7
|
name: "Download Files",
|
|
8
8
|
description: "Browse and select files from SharePoint and get their metadata along with pre-authenticated download URLs (valid ~1 hour). [See the documentation](https://learn.microsoft.com/en-us/graph/api/driveitem-get)",
|
|
9
|
-
version: "0.0.
|
|
9
|
+
version: "0.0.2",
|
|
10
10
|
type: "action",
|
|
11
11
|
annotations: {
|
|
12
12
|
destructiveHint: false,
|
|
@@ -6,7 +6,7 @@ export default {
|
|
|
6
6
|
key: "sharepoint-find-file-by-name",
|
|
7
7
|
name: "Find File by Name",
|
|
8
8
|
description: "Search for a file or folder by name. [See the documentation](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_search)",
|
|
9
|
-
version: "0.1.
|
|
9
|
+
version: "0.1.5",
|
|
10
10
|
type: "action",
|
|
11
11
|
annotations: {
|
|
12
12
|
destructiveHint: false,
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
name: "Find Files in List with Metadata",
|
|
6
6
|
description:
|
|
7
7
|
"Search and filter items in a SharePoint list based on metadata and custom columns. [See docs here](https://learn.microsoft.com/en-us/graph/api/listitem-list)",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.3",
|
|
9
9
|
type: "action",
|
|
10
10
|
annotations: {
|
|
11
11
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-get-excel-table",
|
|
5
5
|
name: "Get Excel Table",
|
|
6
6
|
description: "Retrieve a table from an Excel spreadsheet stored in Sharepoint [See the documentation](https://learn.microsoft.com/en-us/graph/api/table-range?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.7",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-get-file-by-id",
|
|
5
5
|
name: "Get File by ID",
|
|
6
6
|
description: "Retrieves a file by ID. [See the documentation](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_get)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.6",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-get-site",
|
|
5
5
|
name: "Get Site",
|
|
6
6
|
description: "Get a site in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.4",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-list-files-in-folder",
|
|
5
5
|
name: "List Files in Folder",
|
|
6
6
|
description: "Retrieves a list of the files and/or folders directly within a folder. [See the documentation](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.6",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-list-sites",
|
|
5
5
|
name: "List Sites",
|
|
6
6
|
description: "List all sites in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/site-list?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.4",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -8,7 +8,7 @@ export default {
|
|
|
8
8
|
key: "sharepoint-retrieve-file-metadata",
|
|
9
9
|
name: "Retrieve File Metadata",
|
|
10
10
|
description: "Browse and select files from SharePoint to retrieve their metadata (name, size, dates, etc.) without download URLs. [See the documentation](https://learn.microsoft.com/en-us/graph/api/driveitem-get)",
|
|
11
|
-
version: "0.0.
|
|
11
|
+
version: "0.0.2",
|
|
12
12
|
type: "action",
|
|
13
13
|
annotations: {
|
|
14
14
|
destructiveHint: false,
|
|
@@ -6,7 +6,7 @@ export default {
|
|
|
6
6
|
name: "Search and Filter Files",
|
|
7
7
|
description:
|
|
8
8
|
"Search and filter SharePoint files based on metadata and custom columns. This action allows you to query files using SharePoint's custom properties, managed metadata, and other column values. [See the documentation](https://learn.microsoft.com/en-us/graph/api/listitem-list)",
|
|
9
|
-
version: "0.0.
|
|
9
|
+
version: "0.0.3",
|
|
10
10
|
type: "action",
|
|
11
11
|
annotations: {
|
|
12
12
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-search-files",
|
|
5
5
|
name: "Search Files",
|
|
6
6
|
description: "Search for files in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/search-query?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.4",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "sharepoint-search-sites",
|
|
5
5
|
name: "Search Sites",
|
|
6
6
|
description: "Search for sites in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/site-search?view=graph-rest-1.0&tabs=http)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.4",
|
|
8
8
|
type: "action",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: false,
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
key: "sharepoint-update-item",
|
|
6
6
|
name: "Update Item",
|
|
7
7
|
description: "Updates an existing item in Microsoft Sharepoint. [See the documentation](https://learn.microsoft.com/en-us/graph/api/listitem-update?view=graph-rest-1.0&tabs=http)",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.12",
|
|
9
9
|
annotations: {
|
|
10
10
|
destructiveHint: true,
|
|
11
11
|
openWorldHint: true,
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
key: "sharepoint-upload-file",
|
|
6
6
|
name: "Upload File",
|
|
7
7
|
description: "Upload a file to OneDrive. [See the documentation](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_put_content?view=odsp-graph-online)",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.6",
|
|
9
9
|
type: "action",
|
|
10
10
|
annotations: {
|
|
11
11
|
destructiveHint: false,
|
|
@@ -68,13 +68,18 @@ export default {
|
|
|
68
68
|
} = await getFileStreamAndMetadata(filePath);
|
|
69
69
|
const name = filename || metadata.name;
|
|
70
70
|
|
|
71
|
+
const chunks = [];
|
|
72
|
+
for await (const chunk of stream) {
|
|
73
|
+
chunks.push(chunk);
|
|
74
|
+
}
|
|
75
|
+
const buffer = Buffer.concat(chunks);
|
|
76
|
+
|
|
71
77
|
const response = await this.sharepoint.uploadFile({
|
|
72
78
|
siteId,
|
|
73
79
|
driveId,
|
|
74
80
|
uploadFolderId,
|
|
75
81
|
name,
|
|
76
|
-
data:
|
|
77
|
-
$,
|
|
82
|
+
data: buffer,
|
|
78
83
|
});
|
|
79
84
|
|
|
80
85
|
if (response?.id) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipedream/sharepoint",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Pipedream Microsoft Sharepoint Online Components",
|
|
5
5
|
"main": "sharepoint.app.mjs",
|
|
6
6
|
"keywords": [
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@pipedream/platform": "^3.1.1",
|
|
17
16
|
"@microsoft/microsoft-graph-client": "^3.0.7",
|
|
18
|
-
"
|
|
19
|
-
"isomorphic-fetch": "^3.0.0"
|
|
17
|
+
"@pipedream/platform": "^3.1.1",
|
|
18
|
+
"isomorphic-fetch": "^3.0.0",
|
|
19
|
+
"lodash.pickby": "^4.6.0"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/sharepoint.app.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { axios } from "@pipedream/platform";
|
|
2
1
|
import { Client } from "@microsoft/microsoft-graph-client";
|
|
3
|
-
import retry from "async-retry";
|
|
4
2
|
import "isomorphic-fetch";
|
|
5
3
|
import { WEBHOOK_SUBSCRIPTION_EXPIRATION_TIME_MILLISECONDS } from "./common/constants.mjs";
|
|
4
|
+
import pickBy from "lodash.pickby";
|
|
6
5
|
|
|
7
6
|
export default {
|
|
8
7
|
type: "app",
|
|
@@ -360,7 +359,7 @@ export default {
|
|
|
360
359
|
driveId: resolvedDriveId,
|
|
361
360
|
});
|
|
362
361
|
return response.value?.map(({
|
|
363
|
-
id, name, folder, size, lastModifiedDateTime,
|
|
362
|
+
id, name, folder, size, lastModifiedDateTime, webUrl, description,
|
|
364
363
|
}) => ({
|
|
365
364
|
value: JSON.stringify({
|
|
366
365
|
id,
|
|
@@ -369,6 +368,8 @@ export default {
|
|
|
369
368
|
size,
|
|
370
369
|
childCount: folder?.childCount,
|
|
371
370
|
lastModifiedDateTime,
|
|
371
|
+
webUrl,
|
|
372
|
+
description,
|
|
372
373
|
}),
|
|
373
374
|
label: folder
|
|
374
375
|
? `📁 ${name}`
|
|
@@ -378,7 +379,6 @@ export default {
|
|
|
378
379
|
},
|
|
379
380
|
},
|
|
380
381
|
methods: {
|
|
381
|
-
_graphClient: null,
|
|
382
382
|
/**
|
|
383
383
|
* Resolves a potentially wrapped labeled value to its actual value.
|
|
384
384
|
* Pipedream props with withLabel: true wrap values in a special format.
|
|
@@ -431,399 +431,187 @@ export default {
|
|
|
431
431
|
* and includes built-in pagination and type safety.
|
|
432
432
|
*/
|
|
433
433
|
client() {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
getAccessToken: () => Promise.resolve(this._getAccessToken()),
|
|
438
|
-
},
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
return this._graphClient;
|
|
442
|
-
},
|
|
443
|
-
/**
|
|
444
|
-
* Makes a request to Microsoft Graph API with automatic retry logic.
|
|
445
|
-
* Retries on transient errors (5xx, 429) but not on auth/client
|
|
446
|
-
* errors (4xx).
|
|
447
|
-
*
|
|
448
|
-
* @param {Object} options - Request options
|
|
449
|
-
* @param {string} options.path - API path (e.g., "/sites/{siteId}")
|
|
450
|
-
* @param {string} [options.method="GET"] - HTTP method
|
|
451
|
-
* @param {*} [options.content] - Request body for POST/PATCH
|
|
452
|
-
* @param {number} [options.retries=3] - Number of retry attempts
|
|
453
|
-
* @returns {Promise<*>} API response
|
|
454
|
-
*/
|
|
455
|
-
async graphRequest({
|
|
456
|
-
path, method = "GET", content, retries = 3,
|
|
457
|
-
}) {
|
|
458
|
-
return retry(
|
|
459
|
-
async (bail) => {
|
|
460
|
-
try {
|
|
461
|
-
const api = this.client().api(path);
|
|
462
|
-
|
|
463
|
-
switch (method.toUpperCase()) {
|
|
464
|
-
case "GET":
|
|
465
|
-
return await api.get();
|
|
466
|
-
case "POST":
|
|
467
|
-
return await api.post(content);
|
|
468
|
-
case "PATCH":
|
|
469
|
-
return await api.patch(content);
|
|
470
|
-
case "DELETE":
|
|
471
|
-
return await api.delete();
|
|
472
|
-
default:
|
|
473
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
474
|
-
}
|
|
475
|
-
} catch (error) {
|
|
476
|
-
// Don't retry on auth errors or client errors (4xx except 429)
|
|
477
|
-
const status = error.statusCode || error.response?.status;
|
|
478
|
-
if ([
|
|
479
|
-
400,
|
|
480
|
-
401,
|
|
481
|
-
403,
|
|
482
|
-
404,
|
|
483
|
-
].includes(status)) {
|
|
484
|
-
bail(error); // Throw immediately, don't retry
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
throw error; // Retry on other errors
|
|
488
|
-
}
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
retries,
|
|
492
|
-
minTimeout: 1000,
|
|
493
|
-
maxTimeout: 10000,
|
|
494
|
-
onRetry: (error, attempt) => {
|
|
495
|
-
console.log(`Retry attempt ${attempt} after error: ${error.message}`);
|
|
496
|
-
},
|
|
434
|
+
return Client.initWithMiddleware({
|
|
435
|
+
authProvider: {
|
|
436
|
+
getAccessToken: () => Promise.resolve(this._getAccessToken()),
|
|
497
437
|
},
|
|
498
|
-
);
|
|
499
|
-
},
|
|
500
|
-
_baseUrl() {
|
|
501
|
-
return "https://graph.microsoft.com/v1.0";
|
|
502
|
-
},
|
|
503
|
-
_headers(headers) {
|
|
504
|
-
return {
|
|
505
|
-
Authorization: `Bearer ${this._getAccessToken()}`,
|
|
506
|
-
...headers,
|
|
507
|
-
};
|
|
508
|
-
},
|
|
509
|
-
_makeRequest({
|
|
510
|
-
$ = this,
|
|
511
|
-
path,
|
|
512
|
-
url,
|
|
513
|
-
headers,
|
|
514
|
-
...args
|
|
515
|
-
}) {
|
|
516
|
-
return axios($, {
|
|
517
|
-
url: url || `${this._baseUrl()}${path}`,
|
|
518
|
-
headers: this._headers(headers),
|
|
519
|
-
...args,
|
|
520
|
-
});
|
|
521
|
-
},
|
|
522
|
-
/**
|
|
523
|
-
* Makes a request to SharePoint REST API (not Microsoft Graph).
|
|
524
|
-
* Use this for SharePoint-specific features not available in Graph API,
|
|
525
|
-
* such as native SharePoint site groups.
|
|
526
|
-
*
|
|
527
|
-
* @param {Object} options - Request options
|
|
528
|
-
* @param {string} options.siteWebUrl - Full site URL (e.g., "https://tenant.sharepoint.com/sites/MySite")
|
|
529
|
-
* @param {string} options.path - REST API path (e.g., "/web/sitegroups")
|
|
530
|
-
* @param {Object} [options.headers] - Additional headers
|
|
531
|
-
* @returns {Promise<Object>} API response
|
|
532
|
-
* @example
|
|
533
|
-
* // Get SharePoint site groups
|
|
534
|
-
* await this._makeSharePointRestRequest({
|
|
535
|
-
* siteWebUrl: "https://contoso.sharepoint.com/sites/TeamSite",
|
|
536
|
-
* path: "/web/sitegroups"
|
|
537
|
-
* })
|
|
538
|
-
*/
|
|
539
|
-
_makeSharePointRestRequest({
|
|
540
|
-
$ = this,
|
|
541
|
-
siteWebUrl,
|
|
542
|
-
path,
|
|
543
|
-
headers,
|
|
544
|
-
...args
|
|
545
|
-
}) {
|
|
546
|
-
// SharePoint REST API uses the site's webUrl as base
|
|
547
|
-
// e.g., https://tenant.sharepoint.com/sites/MySite/_api/web/sitegroups
|
|
548
|
-
const baseUrl = siteWebUrl.replace(/\/$/, ""); // Remove trailing slash if present
|
|
549
|
-
return axios($, {
|
|
550
|
-
url: `${baseUrl}/_api${path}`,
|
|
551
|
-
headers: this._headers({
|
|
552
|
-
Accept: "application/json;odata=verbose",
|
|
553
|
-
...headers,
|
|
554
|
-
}),
|
|
555
|
-
...args,
|
|
556
438
|
});
|
|
557
439
|
},
|
|
558
440
|
getSite({
|
|
559
|
-
siteId,
|
|
560
|
-
}) {
|
|
561
|
-
return this.
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
});
|
|
565
|
-
},
|
|
566
|
-
/**
|
|
567
|
-
* Lists SharePoint-native site groups using the SharePoint REST API.
|
|
568
|
-
* These are different from Microsoft 365 Groups and can only be accessed via REST API.
|
|
569
|
-
*
|
|
570
|
-
* @param {Object} options - Request options
|
|
571
|
-
* @param {string} options.siteWebUrl - Full site URL
|
|
572
|
-
* @returns {Promise<Object>} Response with groups in d.results array
|
|
573
|
-
* @example
|
|
574
|
-
* const groups = await this.listSharePointSiteGroups({
|
|
575
|
-
* siteWebUrl: "https://contoso.sharepoint.com/sites/TeamSite"
|
|
576
|
-
* });
|
|
577
|
-
* // Returns: { d: { results: [{ Id: 5, Title: "Team Site Members" }, ...] } }
|
|
578
|
-
*/
|
|
579
|
-
listSharePointSiteGroups({
|
|
580
|
-
siteWebUrl, ...args
|
|
581
|
-
}) {
|
|
582
|
-
return this._makeSharePointRestRequest({
|
|
583
|
-
siteWebUrl,
|
|
584
|
-
path: "/web/sitegroups",
|
|
585
|
-
...args,
|
|
586
|
-
});
|
|
587
|
-
},
|
|
588
|
-
/**
|
|
589
|
-
* Gets members of a SharePoint-native site group using the SharePoint REST API.
|
|
590
|
-
* Returns user details including email, display name, and login name.
|
|
591
|
-
*
|
|
592
|
-
* @param {Object} options - Request options
|
|
593
|
-
* @param {string} options.siteWebUrl - Full site URL
|
|
594
|
-
* @param {number} options.groupId - SharePoint group ID
|
|
595
|
-
* @returns {Promise<Object>} Response with users in d.results array
|
|
596
|
-
* @example
|
|
597
|
-
* const members = await this.getSharePointSiteGroupMembers({
|
|
598
|
-
* siteWebUrl: "https://contoso.sharepoint.com/sites/TeamSite",
|
|
599
|
-
* groupId: 5
|
|
600
|
-
* });
|
|
601
|
-
* // Returns: { d: { results: [{ Email: "user@contoso.com", Title: "John Doe" }, ...] } }
|
|
602
|
-
*/
|
|
603
|
-
getSharePointSiteGroupMembers({
|
|
604
|
-
siteWebUrl, groupId, ...args
|
|
605
|
-
}) {
|
|
606
|
-
return this._makeSharePointRestRequest({
|
|
607
|
-
siteWebUrl,
|
|
608
|
-
path: `/web/sitegroups/getbyid(${groupId})/users`,
|
|
609
|
-
...args,
|
|
610
|
-
});
|
|
441
|
+
siteId, params = {},
|
|
442
|
+
} = {}) {
|
|
443
|
+
return this.client().api(`/sites/${siteId}`)
|
|
444
|
+
.query(pickBy(params))
|
|
445
|
+
.get();
|
|
611
446
|
},
|
|
612
|
-
listSites(
|
|
613
|
-
return this.
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
});
|
|
447
|
+
listSites({ params = {} } = {}) {
|
|
448
|
+
return this.client().api("/me/followedSites")
|
|
449
|
+
.query(pickBy(params))
|
|
450
|
+
.get();
|
|
617
451
|
},
|
|
618
|
-
listAllSites({
|
|
619
|
-
params = {}, ...args
|
|
620
|
-
} = {}) {
|
|
452
|
+
listAllSites({ params = {} } = {}) {
|
|
621
453
|
if (!params.search) {
|
|
622
454
|
params.search = "*";
|
|
623
455
|
}
|
|
624
|
-
return this.
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
...args,
|
|
628
|
-
});
|
|
456
|
+
return this.client().api("/sites")
|
|
457
|
+
.query(pickBy(params))
|
|
458
|
+
.get();
|
|
629
459
|
},
|
|
630
460
|
listLists({
|
|
631
|
-
siteId,
|
|
632
|
-
}) {
|
|
633
|
-
return this.
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
});
|
|
461
|
+
siteId, params = {},
|
|
462
|
+
} = {}) {
|
|
463
|
+
return this.client().api(`/sites/${siteId}/lists`)
|
|
464
|
+
.query(pickBy(params))
|
|
465
|
+
.get();
|
|
637
466
|
},
|
|
638
467
|
listColumns({
|
|
639
|
-
siteId, listId,
|
|
640
|
-
}) {
|
|
641
|
-
return this.
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
});
|
|
468
|
+
siteId, listId, params = {},
|
|
469
|
+
} = {}) {
|
|
470
|
+
return this.client().api(`/sites/${siteId}/lists/${listId}/columns`)
|
|
471
|
+
.query(pickBy(params))
|
|
472
|
+
.get();
|
|
645
473
|
},
|
|
646
474
|
listItems({
|
|
647
|
-
siteId, listId,
|
|
648
|
-
}) {
|
|
649
|
-
return this.
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
});
|
|
475
|
+
siteId, listId, params = {},
|
|
476
|
+
} = {}) {
|
|
477
|
+
return this.client().api(`/sites/${siteId}/lists/${listId}/items`)
|
|
478
|
+
.query(pickBy(params))
|
|
479
|
+
.get();
|
|
653
480
|
},
|
|
654
481
|
getListItem({
|
|
655
|
-
siteId, listId, itemId,
|
|
656
|
-
}) {
|
|
657
|
-
return this.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
});
|
|
482
|
+
siteId, listId, itemId, params = {},
|
|
483
|
+
} = {}) {
|
|
484
|
+
return this.client().api(`/sites/${siteId}/lists/${listId}/items/${itemId}`)
|
|
485
|
+
.query(pickBy(params))
|
|
486
|
+
.get();
|
|
661
487
|
},
|
|
662
488
|
listSiteDrives({
|
|
663
|
-
siteId,
|
|
664
|
-
}) {
|
|
665
|
-
return this.
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
});
|
|
489
|
+
siteId, params = {},
|
|
490
|
+
} = {}) {
|
|
491
|
+
return this.client().api(`/sites/${siteId}/drives`)
|
|
492
|
+
.query(pickBy(params))
|
|
493
|
+
.get();
|
|
669
494
|
},
|
|
670
495
|
listDriveItems({
|
|
671
|
-
siteId, driveId,
|
|
672
|
-
}) {
|
|
673
|
-
return this.
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
});
|
|
496
|
+
siteId, driveId, params = {},
|
|
497
|
+
} = {}) {
|
|
498
|
+
return this.client().api(`/sites/${siteId}/drives/${driveId}/root/children`)
|
|
499
|
+
.query(pickBy(params))
|
|
500
|
+
.get();
|
|
677
501
|
},
|
|
678
502
|
listDriveItemsInFolder({
|
|
679
|
-
driveId, folderId,
|
|
680
|
-
}) {
|
|
681
|
-
return this.
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
});
|
|
503
|
+
driveId, folderId, params = {},
|
|
504
|
+
} = {}) {
|
|
505
|
+
return this.client().api(`/drives/${driveId}/items/${folderId}/children`)
|
|
506
|
+
.query(pickBy(params))
|
|
507
|
+
.get();
|
|
685
508
|
},
|
|
686
509
|
createDriveItem({
|
|
687
|
-
siteId, driveId,
|
|
688
|
-
}) {
|
|
689
|
-
return this.
|
|
690
|
-
|
|
691
|
-
method: "POST",
|
|
692
|
-
...args,
|
|
693
|
-
});
|
|
510
|
+
siteId, driveId, data = {},
|
|
511
|
+
} = {}) {
|
|
512
|
+
return this.client().api(`/sites/${siteId}/drives/${driveId}/root/children`)
|
|
513
|
+
.post(data);
|
|
694
514
|
},
|
|
695
515
|
createDriveItemInFolder({
|
|
696
|
-
siteId, folderId,
|
|
697
|
-
}) {
|
|
698
|
-
return this.
|
|
699
|
-
|
|
700
|
-
method: "POST",
|
|
701
|
-
...args,
|
|
702
|
-
});
|
|
516
|
+
siteId, folderId, data = {},
|
|
517
|
+
} = {}) {
|
|
518
|
+
return this.client().api(`/sites/${siteId}/drive/items/${folderId}/children`)
|
|
519
|
+
.post(data);
|
|
703
520
|
},
|
|
704
521
|
createLink({
|
|
705
|
-
siteId, fileId,
|
|
706
|
-
}) {
|
|
707
|
-
return this.
|
|
708
|
-
|
|
709
|
-
method: "POST",
|
|
710
|
-
...args,
|
|
711
|
-
});
|
|
522
|
+
siteId, fileId, data = {},
|
|
523
|
+
} = {}) {
|
|
524
|
+
return this.client().api(`/sites/${siteId}/drive/items/${fileId}/createLink`)
|
|
525
|
+
.post(data);
|
|
712
526
|
},
|
|
713
527
|
listExcelTables({
|
|
714
|
-
siteId, itemId,
|
|
715
|
-
}) {
|
|
716
|
-
return this.
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
});
|
|
528
|
+
siteId, itemId, params = {},
|
|
529
|
+
} = {}) {
|
|
530
|
+
return this.client().api(`/sites/${siteId}/drive/items/${itemId}/workbook/tables`)
|
|
531
|
+
.query(pickBy(params))
|
|
532
|
+
.get();
|
|
720
533
|
},
|
|
721
534
|
getExcelTable({
|
|
722
|
-
siteId, itemId, tableName,
|
|
723
|
-
}) {
|
|
724
|
-
return this.
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
});
|
|
535
|
+
siteId, itemId, tableName, params = {},
|
|
536
|
+
} = {}) {
|
|
537
|
+
return this.client().api(`/sites/${siteId}/drive/items/${itemId}/workbook/tables/${tableName}/range`)
|
|
538
|
+
.query(pickBy(params))
|
|
539
|
+
.get();
|
|
728
540
|
},
|
|
729
541
|
uploadFile({
|
|
730
|
-
siteId, driveId, uploadFolderId, name,
|
|
731
|
-
}) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
headers: {
|
|
738
|
-
"Authorization": `Bearer ${this._getAccessToken()}`,
|
|
739
|
-
},
|
|
740
|
-
...args,
|
|
741
|
-
});
|
|
542
|
+
siteId, driveId, uploadFolderId, name, data,
|
|
543
|
+
} = {}) {
|
|
544
|
+
const path = uploadFolderId
|
|
545
|
+
? `/sites/${siteId}/drives/${driveId}/items/${uploadFolderId}:/${encodeURI(name)}:/content`
|
|
546
|
+
: `/sites/${siteId}/drives/${driveId}/root:/${encodeURI(name)}:/content`;
|
|
547
|
+
return this.client().api(path)
|
|
548
|
+
.put(data);
|
|
742
549
|
},
|
|
743
550
|
getDriveItem({
|
|
744
|
-
siteId, driveId, fileId,
|
|
745
|
-
}) {
|
|
746
|
-
// Use driveId if provided, otherwise fall back to site's default drive
|
|
551
|
+
siteId, driveId, fileId, params = {},
|
|
552
|
+
} = {}) {
|
|
747
553
|
const path = driveId
|
|
748
554
|
? `/drives/${driveId}/items/${fileId}`
|
|
749
555
|
: `/sites/${siteId}/drive/items/${fileId}`;
|
|
750
|
-
return this.
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
});
|
|
556
|
+
return this.client().api(path)
|
|
557
|
+
.query(pickBy(params))
|
|
558
|
+
.get();
|
|
754
559
|
},
|
|
755
560
|
listDriveItemPermissions({
|
|
756
|
-
driveId, itemId,
|
|
757
|
-
}) {
|
|
758
|
-
return this.
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
});
|
|
561
|
+
driveId, itemId, params = {},
|
|
562
|
+
} = {}) {
|
|
563
|
+
return this.client().api(`/drives/${driveId}/items/${itemId}/permissions`)
|
|
564
|
+
.query(pickBy(params))
|
|
565
|
+
.get();
|
|
762
566
|
},
|
|
763
567
|
searchDriveItems({
|
|
764
|
-
siteId, query,
|
|
765
|
-
}) {
|
|
766
|
-
return this.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
)}')`,
|
|
770
|
-
...args,
|
|
771
|
-
});
|
|
568
|
+
siteId, query, params = {},
|
|
569
|
+
} = {}) {
|
|
570
|
+
return this.client().api(`/sites/${siteId}/drive/root/search(q='${encodeURIComponent(query)}')`)
|
|
571
|
+
.query(pickBy(params))
|
|
572
|
+
.get();
|
|
772
573
|
},
|
|
773
574
|
getFile({
|
|
774
|
-
driveId, fileId,
|
|
775
|
-
}) {
|
|
776
|
-
return this.
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
});
|
|
575
|
+
driveId, fileId, params = {},
|
|
576
|
+
} = {}) {
|
|
577
|
+
return this.client().api(`/drives/${driveId}/items/${fileId}/content`)
|
|
578
|
+
.query(pickBy(params))
|
|
579
|
+
.get();
|
|
780
580
|
},
|
|
781
581
|
createList({
|
|
782
|
-
siteId,
|
|
783
|
-
}) {
|
|
784
|
-
return this.
|
|
785
|
-
|
|
786
|
-
method: "POST",
|
|
787
|
-
...args,
|
|
788
|
-
});
|
|
582
|
+
siteId, data = {},
|
|
583
|
+
} = {}) {
|
|
584
|
+
return this.client().api(`/sites/${siteId}/lists`)
|
|
585
|
+
.post(data);
|
|
789
586
|
},
|
|
790
587
|
createItem({
|
|
791
|
-
siteId, listId,
|
|
792
|
-
}) {
|
|
793
|
-
return this.
|
|
794
|
-
|
|
795
|
-
method: "POST",
|
|
796
|
-
...args,
|
|
797
|
-
});
|
|
588
|
+
siteId, listId, data = {},
|
|
589
|
+
} = {}) {
|
|
590
|
+
return this.client().api(`/sites/${siteId}/lists/${listId}/items`)
|
|
591
|
+
.post(data);
|
|
798
592
|
},
|
|
799
593
|
updateItem({
|
|
800
|
-
siteId, listId, itemId,
|
|
801
|
-
}) {
|
|
802
|
-
return this.
|
|
803
|
-
|
|
804
|
-
method: "PATCH",
|
|
805
|
-
...args,
|
|
806
|
-
});
|
|
594
|
+
siteId, listId, itemId, data = {},
|
|
595
|
+
} = {}) {
|
|
596
|
+
return this.client().api(`/sites/${siteId}/lists/${listId}/items/${itemId}/fields`)
|
|
597
|
+
.patch(data);
|
|
807
598
|
},
|
|
808
|
-
listGroups(
|
|
809
|
-
return this.
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
});
|
|
599
|
+
listGroups({ params = {} } = {}) {
|
|
600
|
+
return this.client().api("/groups")
|
|
601
|
+
.query(pickBy(params))
|
|
602
|
+
.get();
|
|
813
603
|
},
|
|
814
|
-
listUsers(
|
|
815
|
-
return this.
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
});
|
|
604
|
+
listUsers({ params = {} } = {}) {
|
|
605
|
+
return this.client().api("/users")
|
|
606
|
+
.query(pickBy(params))
|
|
607
|
+
.get();
|
|
819
608
|
},
|
|
820
609
|
listGroupMembers({
|
|
821
|
-
groupId,
|
|
822
|
-
}) {
|
|
823
|
-
return this.
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
});
|
|
610
|
+
groupId, params = {},
|
|
611
|
+
} = {}) {
|
|
612
|
+
return this.client().api(`/groups/${groupId}/members`)
|
|
613
|
+
.query(pickBy(params))
|
|
614
|
+
.get();
|
|
827
615
|
},
|
|
828
616
|
/**
|
|
829
617
|
* Get delta changes for a drive using Microsoft Graph delta query.
|
|
@@ -847,26 +635,19 @@ export default {
|
|
|
847
635
|
* });
|
|
848
636
|
*/
|
|
849
637
|
getDriveDelta({
|
|
850
|
-
driveId, deltaLink,
|
|
851
|
-
}) {
|
|
852
|
-
// If we have a deltaLink/nextLink, use it as full URL; otherwise build path
|
|
638
|
+
driveId, deltaLink,
|
|
639
|
+
} = {}) {
|
|
853
640
|
if (deltaLink) {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
});
|
|
641
|
+
const path = deltaLink.replace(/^https:\/\/graph\.microsoft\.com\/v[^/]+/, "");
|
|
642
|
+
return this.client().api(path)
|
|
643
|
+
.get();
|
|
858
644
|
}
|
|
859
|
-
return this.
|
|
860
|
-
|
|
861
|
-
...args,
|
|
862
|
-
});
|
|
645
|
+
return this.client().api(`/drives/${driveId}/root/delta`)
|
|
646
|
+
.get();
|
|
863
647
|
},
|
|
864
|
-
searchQuery(
|
|
865
|
-
return this.
|
|
866
|
-
|
|
867
|
-
path: "/search/query",
|
|
868
|
-
...args,
|
|
869
|
-
});
|
|
648
|
+
searchQuery({ data = {} } = {}) {
|
|
649
|
+
return this.client().api("/search/query")
|
|
650
|
+
.post(data);
|
|
870
651
|
},
|
|
871
652
|
async *paginate({
|
|
872
653
|
fn, args,
|
|
@@ -913,24 +694,19 @@ export default {
|
|
|
913
694
|
* });
|
|
914
695
|
*/
|
|
915
696
|
createSubscription({
|
|
916
|
-
resource, notificationUrl, changeType = "updated", clientState,
|
|
917
|
-
}) {
|
|
697
|
+
resource, notificationUrl, changeType = "updated", clientState,
|
|
698
|
+
} = {}) {
|
|
918
699
|
const expirationDateTime = new Date(
|
|
919
700
|
Date.now() + WEBHOOK_SUBSCRIPTION_EXPIRATION_TIME_MILLISECONDS,
|
|
920
701
|
).toISOString();
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
method: "POST",
|
|
924
|
-
path: "/subscriptions",
|
|
925
|
-
data: {
|
|
702
|
+
return this.client().api("/subscriptions")
|
|
703
|
+
.post({
|
|
926
704
|
changeType,
|
|
927
705
|
notificationUrl,
|
|
928
706
|
resource,
|
|
929
707
|
expirationDateTime,
|
|
930
708
|
clientState,
|
|
931
|
-
}
|
|
932
|
-
...args,
|
|
933
|
-
});
|
|
709
|
+
});
|
|
934
710
|
},
|
|
935
711
|
/**
|
|
936
712
|
* Updates a subscription's expiration time (renewal).
|
|
@@ -945,21 +721,14 @@ export default {
|
|
|
945
721
|
* subscriptionId: "abc123-def456"
|
|
946
722
|
* });
|
|
947
723
|
*/
|
|
948
|
-
updateSubscription({
|
|
949
|
-
subscriptionId, ...args
|
|
950
|
-
}) {
|
|
724
|
+
updateSubscription({ subscriptionId } = {}) {
|
|
951
725
|
const expirationDateTime = new Date(
|
|
952
726
|
Date.now() + WEBHOOK_SUBSCRIPTION_EXPIRATION_TIME_MILLISECONDS,
|
|
953
727
|
).toISOString();
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
method: "PATCH",
|
|
957
|
-
path: `/subscriptions/${subscriptionId}`,
|
|
958
|
-
data: {
|
|
728
|
+
return this.client().api(`/subscriptions/${subscriptionId}`)
|
|
729
|
+
.patch({
|
|
959
730
|
expirationDateTime,
|
|
960
|
-
}
|
|
961
|
-
...args,
|
|
962
|
-
});
|
|
731
|
+
});
|
|
963
732
|
},
|
|
964
733
|
/**
|
|
965
734
|
* Deletes a subscription. Call this when deactivating a webhook source
|
|
@@ -974,14 +743,9 @@ export default {
|
|
|
974
743
|
* subscriptionId: "abc123-def456"
|
|
975
744
|
* });
|
|
976
745
|
*/
|
|
977
|
-
deleteSubscription({
|
|
978
|
-
subscriptionId
|
|
979
|
-
|
|
980
|
-
return this._makeRequest({
|
|
981
|
-
method: "DELETE",
|
|
982
|
-
path: `/subscriptions/${subscriptionId}`,
|
|
983
|
-
...args,
|
|
984
|
-
});
|
|
746
|
+
deleteSubscription({ subscriptionId } = {}) {
|
|
747
|
+
return this.client().api(`/subscriptions/${subscriptionId}`)
|
|
748
|
+
.delete();
|
|
985
749
|
},
|
|
986
750
|
},
|
|
987
751
|
};
|
|
@@ -4,9 +4,9 @@ import { WEBHOOK_SUBSCRIPTION_RENEWAL_SECONDS } from "../../common/constants.mjs
|
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
6
|
key: "sharepoint-updated-file-instant",
|
|
7
|
-
name: "
|
|
8
|
-
description: "Emit new event when specific files are updated in a SharePoint document library",
|
|
9
|
-
version: "0.0.
|
|
7
|
+
name: "File Updated or Deleted (Instant)",
|
|
8
|
+
description: "Emit a new event when specific files are updated or deleted in a SharePoint document library",
|
|
9
|
+
version: "0.0.3",
|
|
10
10
|
type: "source",
|
|
11
11
|
dedupe: "unique",
|
|
12
12
|
props: {
|
|
@@ -67,8 +67,8 @@ export default {
|
|
|
67
67
|
],
|
|
68
68
|
label: "Files to Monitor",
|
|
69
69
|
description:
|
|
70
|
-
"Select one or more files to monitor for
|
|
71
|
-
"You'll receive a real-time event whenever any of these files are modified.\n\n" +
|
|
70
|
+
"Select one or more files to monitor for changes. " +
|
|
71
|
+
"You'll receive a real-time event whenever any of these files are modified or deleted.\n\n" +
|
|
72
72
|
"**Important:** Only the selected files will trigger events. Changes to other files in the drive will be ignored. " +
|
|
73
73
|
"This ensures you only receive notifications for the documents you care about.",
|
|
74
74
|
},
|
|
@@ -101,8 +101,39 @@ export default {
|
|
|
101
101
|
clientState,
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
// Store the file IDs we're monitoring (unwrap labeled values)
|
|
105
|
-
const
|
|
104
|
+
// Store the file IDs we're monitoring (unwrap labeled values and parse JSON)
|
|
105
|
+
const wrappedFileIds = this.sharepoint.resolveWrappedArrayValues(this.fileIds);
|
|
106
|
+
// Parse JSON strings to extract just the IDs, handle objects, and trim strings
|
|
107
|
+
const fileIds = wrappedFileIds.map((fileId) => {
|
|
108
|
+
// Handle object values directly
|
|
109
|
+
if (typeof fileId === "object" && fileId !== null) {
|
|
110
|
+
if (!fileId.id) {
|
|
111
|
+
console.log(`Warning: Object fileId missing 'id' field: ${JSON.stringify(fileId)}`);
|
|
112
|
+
return String(fileId);
|
|
113
|
+
}
|
|
114
|
+
return fileId.id;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Handle string values - trim whitespace first
|
|
118
|
+
if (typeof fileId === "string") {
|
|
119
|
+
const trimmedFileId = fileId.trim();
|
|
120
|
+
if (trimmedFileId.startsWith("{")) {
|
|
121
|
+
try {
|
|
122
|
+
const parsed = JSON.parse(trimmedFileId);
|
|
123
|
+
if (!parsed || !parsed.id) {
|
|
124
|
+
throw new Error("Parsed object missing 'id' field");
|
|
125
|
+
}
|
|
126
|
+
return parsed.id;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.log(`Warning: Failed to parse fileId: ${trimmedFileId}, error: ${e.message}`);
|
|
129
|
+
return trimmedFileId;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return trimmedFileId;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return fileId;
|
|
136
|
+
});
|
|
106
137
|
this._setMonitoredFileIds(fileIds);
|
|
107
138
|
|
|
108
139
|
// Initialize delta tracking - get current state so we only see future changes
|
|
@@ -220,10 +251,23 @@ export default {
|
|
|
220
251
|
}
|
|
221
252
|
},
|
|
222
253
|
generateMeta(file) {
|
|
223
|
-
|
|
254
|
+
// Use lastModifiedDateTime for updated files, deletedDateTime for deleted files
|
|
255
|
+
// Fall back to current time only if neither is available
|
|
256
|
+
let ts;
|
|
257
|
+
if (file.lastModifiedDateTime) {
|
|
258
|
+
ts = Date.parse(file.lastModifiedDateTime);
|
|
259
|
+
} else if (file.deletedDateTime) {
|
|
260
|
+
ts = Date.parse(file.deletedDateTime);
|
|
261
|
+
} else {
|
|
262
|
+
ts = Date.now();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const action = file.deleted
|
|
266
|
+
? "deleted"
|
|
267
|
+
: "updated";
|
|
224
268
|
return {
|
|
225
269
|
id: `${file.id}-${ts}`,
|
|
226
|
-
summary: `File
|
|
270
|
+
summary: `File ${action}: ${file.name}`,
|
|
227
271
|
ts,
|
|
228
272
|
};
|
|
229
273
|
},
|
|
@@ -272,8 +316,8 @@ export default {
|
|
|
272
316
|
|
|
273
317
|
const validNotifications = body.value.filter((notification) => {
|
|
274
318
|
if (notification.clientState !== clientState) {
|
|
275
|
-
console.
|
|
276
|
-
`Ignoring notification with unexpected clientState: ${notification.clientState}`,
|
|
319
|
+
console.log(
|
|
320
|
+
`Warning: Ignoring notification with unexpected clientState: ${notification.clientState}`,
|
|
277
321
|
);
|
|
278
322
|
return false;
|
|
279
323
|
}
|
|
@@ -313,8 +357,9 @@ export default {
|
|
|
313
357
|
});
|
|
314
358
|
|
|
315
359
|
// Find files that changed and are in our monitored list
|
|
360
|
+
// Include both updated files (item.file) and deleted files (item.deleted)
|
|
316
361
|
for (const item of deltaResponse.value || []) {
|
|
317
|
-
if (item.file && monitoredFileIds.includes(item.id)) {
|
|
362
|
+
if ((item.file || item.deleted) && monitoredFileIds.includes(item.id)) {
|
|
318
363
|
changedFiles.push(item);
|
|
319
364
|
}
|
|
320
365
|
}
|
|
@@ -336,8 +381,9 @@ export default {
|
|
|
336
381
|
// Emit events for each changed file
|
|
337
382
|
for (const file of changedFiles) {
|
|
338
383
|
// Delta response may not include downloadUrl - fetch fresh if needed
|
|
384
|
+
// Skip fetching download URL for deleted files (they no longer exist)
|
|
339
385
|
let downloadUrl = file["@microsoft.graph.downloadUrl"];
|
|
340
|
-
if (!downloadUrl) {
|
|
386
|
+
if (!downloadUrl && !file.deleted) {
|
|
341
387
|
try {
|
|
342
388
|
const freshFile = await this.sharepoint.getDriveItem({
|
|
343
389
|
driveId,
|