Skip to content

Commit e6d8ccd

Browse files
committed
fix(kb-connectors): valuesEqual treats legacy scalar as equal to multi-array
Existing connectors created before multi-select store sourceConfig values as scalars (e.g. projectKey: "ENG"). With the field now declared multi: true, resolveSourceConfig returns an array (["ENG"]), and the original valuesEqual fell through to a strict reference comparison — falsely flagging unsaved changes on open and triggering an unnecessary string→array shape rewrite on save. valuesEqual now normalizes both sides to string[] via CSV-split when either is an array, so persisted scalar and in-memory array of the same content compare equal. Single-value (non-multi) fields keep strict string equality.
1 parent 7edb738 commit e6d8ccd

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/edit-connector-modal/edit-connector-modal.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,40 @@ function readPersistedCanonicalModes(
6767

6868
/**
6969
* Deep equality for sourceConfig values (string, string[], or undefined/null).
70-
* Empty string and empty array are treated as equivalent to absence.
70+
*
71+
* Empty string, empty array, and nullish are treated as equivalent to absence.
72+
* When either side is an array (multi-value field), both sides are normalized
73+
* to string[] via CSV-split-and-trim so a persisted legacy scalar `"ENG"`
74+
* compares equal to an in-memory `["ENG"]` and a persisted CSV `"ENG,PROJ"`
75+
* compares equal to `["ENG","PROJ"]`. Without this, opening edit on a
76+
* pre-multi-select connector would falsely show unsaved changes.
7177
*/
7278
function valuesEqual(a: unknown, b: unknown): boolean {
7379
const isEmpty = (v: unknown): boolean => {
7480
if (v == null) return true
7581
if (Array.isArray(v)) return v.length === 0
76-
if (typeof v === 'string') return v === ''
82+
if (typeof v === 'string') return v.trim() === ''
7783
return false
7884
}
7985
if (isEmpty(a) && isEmpty(b)) return true
80-
if (Array.isArray(a) && Array.isArray(b)) {
81-
if (a.length !== b.length) return false
82-
for (let i = 0; i < a.length; i++) {
83-
if (a[i] !== b[i]) return false
86+
87+
const toArray = (v: unknown): string[] | null => {
88+
if (Array.isArray(v)) return v.filter((x): x is string => typeof x === 'string')
89+
if (typeof v === 'string') {
90+
return v
91+
.split(',')
92+
.map((s) => s.trim())
93+
.filter(Boolean)
94+
}
95+
return null
96+
}
97+
98+
if (Array.isArray(a) || Array.isArray(b)) {
99+
const arrA = toArray(a) ?? []
100+
const arrB = toArray(b) ?? []
101+
if (arrA.length !== arrB.length) return false
102+
for (let i = 0; i < arrA.length; i++) {
103+
if (arrA[i] !== arrB[i]) return false
84104
}
85105
return true
86106
}

0 commit comments

Comments
 (0)