Skip to content

Commit d2ee39e

Browse files
committed
fix(asana): honour the pinned-project exception on the task rehydrate path
listDocuments deliberately keeps syncing a project the user pinned via the `project` config field even once it is archived, but getDocument ignored sourceConfig and applied the all-parents-archived exclusion unconditionally. For a pinned archived project the listing kept emitting its tasks while every hydration returned null, so new tasks were dropped as empty and already-indexed ones were frozen at their last content. isTaskUnderActiveProject now takes the pinned project gid and keeps any task reachable through it, matching the listing exactly. The unpinned path is unchanged and still fails open on missing/non-boolean archived values.
1 parent 2f909fb commit d2ee39e

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

apps/sim/connectors/asana/asana.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,30 @@ describe('isTaskUnderActiveProject', () => {
118118
} as unknown as typeof baseTask)
119119
).toBe(true)
120120
})
121+
122+
it.concurrent('keeps a task reachable through the pinned project even once archived', () => {
123+
expect(
124+
isTaskUnderActiveProject(
125+
{
126+
...baseTask,
127+
projects: [{ gid: 'p1', name: 'Pinned', archived: true }],
128+
},
129+
'p1'
130+
)
131+
).toBe(true)
132+
})
133+
134+
it.concurrent('still excludes an all-archived task when the pinned project is elsewhere', () => {
135+
expect(
136+
isTaskUnderActiveProject(
137+
{
138+
...baseTask,
139+
projects: [{ gid: 'p1', name: 'Old', archived: true }],
140+
},
141+
'p9'
142+
)
143+
).toBe(false)
144+
})
121145
})
122146

123147
describe('decideTaskCap', () => {

apps/sim/connectors/asana/asana.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,17 @@ export function isActiveProject(project: AsanaProject): boolean {
113113
* array, or any entry whose `archived` is missing or non-boolean is kept. A
114114
* task that still sits in at least one active project is kept, matching the
115115
* listing, which reaches it through that active project.
116+
*
117+
* `pinnedProjectGid` mirrors the listing's pinned-project exception: when the
118+
* user configured a specific `project`, the listing keeps syncing it even once
119+
* archived, so a task reachable through that project must survive rehydration
120+
* too. Without this the listing would keep emitting the task while every
121+
* hydration returned `null`, stranding it as permanently empty.
116122
*/
117-
export function isTaskUnderActiveProject(task: AsanaTask): boolean {
123+
export function isTaskUnderActiveProject(task: AsanaTask, pinnedProjectGid?: string): boolean {
118124
const projects = task.projects
119125
if (!Array.isArray(projects) || projects.length === 0) return true
126+
if (pinnedProjectGid && projects.some((project) => project?.gid === pinnedProjectGid)) return true
120127
return !projects.every((project) => project?.archived === true)
121128
}
122129

@@ -382,9 +389,10 @@ export const asanaConnector: ConnectorConfig = {
382389

383390
getDocument: async (
384391
accessToken: string,
385-
_sourceConfig: Record<string, unknown>,
392+
sourceConfig: Record<string, unknown>,
386393
externalId: string
387394
): Promise<ExternalDocument | null> => {
395+
const pinnedProjectGid = (sourceConfig.project as string) || undefined
388396
try {
389397
const result = await asanaGet<{ data: AsanaTask }>(
390398
accessToken,
@@ -394,7 +402,7 @@ export const asanaConnector: ConnectorConfig = {
394402

395403
if (!task) return null
396404

397-
if (!isTaskUnderActiveProject(task)) {
405+
if (!isTaskUnderActiveProject(task, pinnedProjectGid)) {
398406
logger.info('Skipping Asana task whose projects are all archived', { externalId })
399407
return null
400408
}

0 commit comments

Comments
 (0)