Skip to content

Commit 49a9cf0

Browse files
committed
fix(microsoft): shared toStringOrNull in AzDO mapper, null relations when unexpanded, per-file SharePoint name errors
1 parent bbf66fe commit 49a9cf0

5 files changed

Lines changed: 35 additions & 24 deletions

File tree

‎apps/docs/content/docs/integrations/azure_devops.mdx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ Execute a WIQL query to search for work items in Azure DevOps and return full fi
400400
| ↳ `changedBy` | string | Display name of the last user to change the work item |
401401
| ↳ `changedDate` | string | ISO 8601 last-changed timestamp |
402402
| ↳ `webUrl` | string | Browser URL for the work item |
403-
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\) |
403+
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\); null when the response did not include relations \(Create and Update do not expand them\) |
404404
| ↳ `rel` | string | Relation type |
405405
| ↳ `url` | string | URL of the linked resource |
406406
| ↳ `attributes` | json | Link attributes \(name, comment, isLocked\) |
@@ -447,7 +447,7 @@ Fetch full details of a single work item by ID from Azure DevOps, including titl
447447
| ↳ `changedBy` | string | Display name of the last user to change the work item |
448448
| ↳ `changedDate` | string | ISO 8601 last-changed timestamp |
449449
| ↳ `webUrl` | string | Browser URL for the work item |
450-
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\) |
450+
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\); null when the response did not include relations \(Create and Update do not expand them\) |
451451
| ↳ `rel` | string | Relation type |
452452
| ↳ `url` | string | URL of the linked resource |
453453
| ↳ `attributes` | json | Link attributes \(name, comment, isLocked\) |
@@ -496,7 +496,7 @@ Fetch full details for multiple work items by ID from Azure DevOps. Pass comma-s
496496
| ↳ `changedBy` | string | Display name of the last user to change the work item |
497497
| ↳ `changedDate` | string | ISO 8601 last-changed timestamp |
498498
| ↳ `webUrl` | string | Browser URL for the work item |
499-
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\) |
499+
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\); null when the response did not include relations \(Create and Update do not expand them\) |
500500
| ↳ `rel` | string | Relation type |
501501
| ↳ `url` | string | URL of the linked resource |
502502
| ↳ `attributes` | json | Link attributes \(name, comment, isLocked\) |
@@ -556,7 +556,7 @@ Create a new Basic-process work item (Issue, Task, or Epic) in Azure DevOps. Ret
556556
| ↳ `changedBy` | string | Display name of the last user to change the work item |
557557
| ↳ `changedDate` | string | ISO 8601 last-changed timestamp |
558558
| ↳ `webUrl` | string | Browser URL for the work item |
559-
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\) |
559+
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\); null when the response did not include relations \(Create and Update do not expand them\) |
560560
| ↳ `rel` | string | Relation type |
561561
| ↳ `url` | string | URL of the linked resource |
562562
| ↳ `attributes` | json | Link attributes \(name, comment, isLocked\) |
@@ -617,7 +617,7 @@ Update one or more fields on an existing work item in Azure DevOps. Provide only
617617
| ↳ `changedBy` | string | Display name of the last user to change the work item |
618618
| ↳ `changedDate` | string | ISO 8601 last-changed timestamp |
619619
| ↳ `webUrl` | string | Browser URL for the work item |
620-
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\) |
620+
| ↳ `relations` | array | Links to other work items, attachments, and artifacts \(rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes\); null when the response did not include relations \(Create and Update do not expand them\) |
621621
| ↳ `rel` | string | Relation type |
622622
| ↳ `url` | string | URL of the linked resource |
623623
| ↳ `attributes` | json | Link attributes \(name, comment, isLocked\) |

‎apps/sim/lib/internal/sharepoint/operations.ts‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ export async function executeSharePointUploadFile(
120120
const userFiles = processFilesToUserFiles(input.files, context.requestId, logger)
121121
if (userFiles.length === 0) return failureResponse('No valid files to upload', 400)
122122

123+
try {
124+
buildUploadUrl(input, input.fileName || userFiles[0]?.name || 'file')
125+
} catch (error) {
126+
return failureResponse(getErrorMessage(error, 'Invalid upload path'), 400)
127+
}
128+
123129
const client = new SharePointClient(input.accessToken, context.signal)
124130
const uploadedFiles: SharePointUploadedItem[] = []
125131
const skippedFiles: SharepointSkippedFile[] = []
@@ -142,7 +148,12 @@ export async function executeSharePointUploadFile(
142148
try {
143149
uploadUrls = buildUploadUrl(input, fileName)
144150
} catch (error) {
145-
return failureResponse(getErrorMessage(error, 'Invalid upload path'), 400)
151+
errors.push({
152+
name: fileName,
153+
status: 400,
154+
error: getErrorMessage(error, 'Invalid upload path'),
155+
})
156+
continue
146157
}
147158
const { url, replaceUrl } = uploadUrls
148159
const skipOversized = (size: number) => {

‎apps/sim/tools/azure_devops/types.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ export interface AzureDevOpsWorkItem {
300300
changedBy?: string | null
301301
changedDate?: string | null
302302
webUrl?: string | null
303-
relations?: AzureDevOpsWorkItemRelation[]
303+
relations?: AzureDevOpsWorkItemRelation[] | null
304304
fields?: Record<string, unknown>
305305
}
306306

‎apps/sim/tools/azure_devops/utils.ts‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { toStringOrNull } from '@sim/utils/coerce'
12
import {
23
DEFAULT_MAX_ERROR_BODY_BYTES,
34
readResponseJsonWithLimit,
@@ -127,30 +128,28 @@ export function mapWorkItem(raw: AzureDevOpsRawWorkItem): AzureDevOpsWorkItem {
127128
areaPath: (fields['System.AreaPath'] as string | undefined) ?? '',
128129
url: raw.url,
129130
rev: raw.rev ?? null,
130-
description: stringField(fields['System.Description']),
131-
iterationPath: stringField(fields['System.IterationPath']),
132-
reason: stringField(fields['System.Reason']),
133-
tags: stringField(fields['System.Tags']),
131+
description: toStringOrNull(fields['System.Description']),
132+
iterationPath: toStringOrNull(fields['System.IterationPath']),
133+
reason: toStringOrNull(fields['System.Reason']),
134+
tags: toStringOrNull(fields['System.Tags']),
134135
priority: typeof priority === 'number' ? priority : null,
135136
assignedToUniqueName: assignedTo?.uniqueName ?? null,
136137
createdBy: identityField(fields['System.CreatedBy'])?.displayName ?? null,
137-
createdDate: stringField(fields['System.CreatedDate']),
138+
createdDate: toStringOrNull(fields['System.CreatedDate']),
138139
changedBy: identityField(fields['System.ChangedBy'])?.displayName ?? null,
139-
changedDate: stringField(fields['System.ChangedDate']),
140+
changedDate: toStringOrNull(fields['System.ChangedDate']),
140141
webUrl: raw._links?.html?.href ?? null,
141-
relations: (raw.relations ?? []).map((relation) => ({
142-
rel: relation.rel,
143-
url: relation.url,
144-
attributes: relation.attributes ?? {},
145-
})),
142+
relations: raw.relations
143+
? raw.relations.map((relation) => ({
144+
rel: relation.rel,
145+
url: relation.url,
146+
attributes: relation.attributes ?? {},
147+
}))
148+
: null,
146149
fields,
147150
}
148151
}
149152

150-
function stringField(value: unknown): string | null {
151-
return typeof value === 'string' ? value : null
152-
}
153-
154153
function identityField(value: unknown): AzureDevOpsIdentityRef | null {
155154
return value && typeof value === 'object' ? (value as AzureDevOpsIdentityRef) : null
156155
}
@@ -232,8 +231,9 @@ export const WORK_ITEM_DETAIL_OUTPUT_PROPERTIES: Record<string, OutputProperty>
232231
relations: {
233232
type: 'array',
234233
description:
235-
'Links to other work items, attachments, and artifacts (rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes)',
234+
'Links to other work items, attachments, and artifacts (rel such as System.LinkTypes.Hierarchy-Forward or AttachedFile, url, attributes); null when the response did not include relations (Create and Update do not expand them)',
236235
optional: true,
236+
nullable: true,
237237
items: {
238238
type: 'object',
239239
properties: {

‎apps/sim/tools/generated/tool-outputs.ts‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)