new-file-in-subfolders.ts•6.08 kB
import { microsoftSharePointAuth } from '../../';
import {
createTrigger,
TriggerStrategy,
Property,
DropdownOption,
PiecePropValueSchema,
} from '@activepieces/pieces-framework';
import { microsoftSharePointCommon } from '../common';
import { Client, PageCollection } from '@microsoft/microsoft-graph-client';
import { DriveItem } from '@microsoft/microsoft-graph-types';
const clientState = 'activepieces_sharepoint_subfolder_trigger';
export const newFileInSubfoldersTrigger = createTrigger({
auth: microsoftSharePointAuth,
name: 'new_file_in_subfolders',
displayName: 'New File in Subfolders',
description: 'Fires when a new file is added anywhere in the first-level subfolders of a folder. Note: This trigger will not monitor subfolders created after the flow is activated.',
props: {
siteId: microsoftSharePointCommon.siteId,
driveId: microsoftSharePointCommon.driveId,
parentFolderId: Property.Dropdown({
displayName: 'Parent Folder',
description: 'The parent folder whose subfolders you want to monitor.',
required: true,
refreshers: ['siteId', 'driveId'],
options: async ({ auth, siteId, driveId }) => {
if (!auth || !siteId || !driveId) {
return {
disabled: true,
placeholder: 'Select a site and drive first.',
options: [],
};
}
const authValue = auth as PiecePropValueSchema<
typeof microsoftSharePointAuth
>;
const client = Client.initWithMiddleware({
authProvider: {
getAccessToken: () => Promise.resolve(authValue.access_token),
},
});
const options: DropdownOption<string>[] = [
{ label: 'Root Folder', value: 'root' },
];
let response: PageCollection = await client
.api(
`/drives/${driveId}/root/children?$filter=folder ne null&$select=id,name`
)
.get();
while (response.value.length > 0) {
for (const item of response.value as DriveItem[]) {
options.push({ label: item.name!, value: item.id! });
}
if (response['@odata.nextLink']) {
response = await client.api(response['@odata.nextLink']).get();
} else {
break;
}
}
return { disabled: false, options };
},
}),
},
type: TriggerStrategy.WEBHOOK,
sampleData: {
"id": "01DRYVE_ID_GOES_HERE",
"name": "New-File-In-Subfolder.pdf",
"webUrl": "https://contoso.sharepoint.com/Shared%20Documents/SubfolderA/New-File-In-Subfolder.pdf",
"size": 54321,
"createdDateTime": "2025-09-26T14:30:00Z",
"lastModifiedDateTime": "2025-09-26T14:30:00Z",
"file": { "mimeType": "application/pdf" },
"parentReference": { "id": "SUBFOLDER_ID_HERE" }
},
async onEnable(context) {
const { siteId, driveId, parentFolderId } = context.propsValue;
const client = Client.initWithMiddleware({
authProvider: {
getAccessToken: () => Promise.resolve(context.auth.access_token),
},
});
try {
const effectiveParentId = parentFolderId === 'root'
? (await client.api(`/drives/${driveId}/root`).get()).id
: parentFolderId;
const subfoldersResponse = await client.api(`/drives/${driveId}/items/${effectiveParentId}/children?$filter=folder ne null&$select=id`).get();
const subfolders = subfoldersResponse.value as DriveItem[];
const expirationDateTime = new Date();
expirationDateTime.setDate(expirationDateTime.getDate() + 2);
const subscriptionPromises = subfolders.map(folder =>
client.api('/subscriptions').post({
changeType: 'created',
notificationUrl: context.webhookUrl,
resource: `/sites/${siteId}/drive/items/${folder.id}/children`,
expirationDateTime: expirationDateTime.toISOString(),
clientState: clientState,
})
);
const settledSubscriptions = await Promise.allSettled(subscriptionPromises);
const subscriptionIds = settledSubscriptions
.filter(res => res.status === 'fulfilled')
.map(res => (res as PromiseFulfilledResult<any>).value.id);
await context.store.put('subscriptionIds', subscriptionIds);
} catch (error: any) {
throw new Error(`Failed to create subscriptions: ${error.message || 'Unknown error'}`);
}
},
async onDisable(context) {
const subscriptionIds = await context.store.get<string[]>('subscriptionIds');
if (subscriptionIds && subscriptionIds.length > 0) {
const client = Client.initWithMiddleware({
authProvider: {
getAccessToken: () => Promise.resolve(context.auth.access_token),
},
});
const deletionPromises = subscriptionIds.map(id =>
client.api(`/subscriptions/${id}`).delete().catch(err => console.error(`Failed to delete subscription ${id}:`, err))
);
await Promise.allSettled(deletionPromises);
}
await context.store.delete('subscriptionIds');
},
async run(context) {
const notifications = (context.payload.body as { value: any[] })?.value;
if (!notifications || !Array.isArray(notifications)) {
return [];
}
const validNotifications = notifications.filter(
(notif) => notif.clientState === clientState
);
if (validNotifications.length === 0) {
return [];
}
const client = Client.initWithMiddleware({
authProvider: {
getAccessToken: () => Promise.resolve(context.auth.access_token),
},
});
const newFilePayloads = [];
for (const notification of validNotifications) {
try {
const newFile = await client.api(notification.resource).get();
if (newFile.file) {
newFilePayloads.push(newFile);
}
} catch (error) {
console.error('Error fetching file from notification:', error);
}
}
return newFilePayloads;
},
});