-
Notifications
You must be signed in to change notification settings - Fork 0
fix: improve export fidelity for CSV, Excel, and query results (#69, #70, #72, #73, #76, #79, #80) #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: improve export fidelity for CSV, Excel, and query results (#69, #70, #72, #73, #76, #79, #80) #119
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,18 +50,28 @@ export async function queryAllRecords( | |
| } | ||
|
|
||
| /** | ||
| * Derives the set of column names present across the first `sampleSize` records, | ||
| * excluding Salesforce's `attributes` envelope. Stable order of first appearance. | ||
| * Derives the set of column names present across all loaded records, | ||
| * excluding Salesforce's `attributes` envelope at any nesting level. | ||
| * Stable order of first appearance. | ||
| */ | ||
| export function deriveColumns(records: Record<string, unknown>[], sampleSize = 50): string[] { | ||
| export function deriveColumns(records: Record<string, unknown>[]): string[] { | ||
| const cols: string[] = []; | ||
| const seen = new Set<string>(); | ||
| for (const record of records.slice(0, sampleSize)) { | ||
| for (const key of Object.keys(record)) { | ||
| if (key === 'attributes' || seen.has(key)) continue; | ||
| seen.add(key); | ||
| cols.push(key); | ||
| } | ||
| for (const record of records) { | ||
| collectKeys(record, '', seen, cols); | ||
| } | ||
| return cols; | ||
| } | ||
|
|
||
| function collectKeys(value: unknown, prefix: string, seen: Set<string>, cols: string[]): void { | ||
| if (value === null || value === undefined || typeof value !== 'object' || Array.isArray(value)) return; | ||
| for (const [k, v] of Object.entries(value as Record<string, unknown>)) { | ||
| if (k === 'attributes') continue; | ||
| const fullKey = prefix ? `${prefix}.${k}` : k; | ||
| if (!seen.has(fullKey)) { | ||
| seen.add(fullKey); | ||
| cols.push(fullKey); | ||
| } | ||
| collectKeys(v, fullKey, seen, cols); | ||
|
Comment on lines
+71
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For scheduled queries containing relationships, this adds headers such as Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enabling
dynamicTypingfor every column makes Papa Parse infer types solely from CSV contents, without Salesforce field metadata. Consequently, text values such as postal codes or external IDs containing00123become numbers and lose leading zeroes, while ISO datetime strings becomeDateobjects; thoseDateobjects are subsequently omitted byflattenRecordbecause it traverses them withObject.entries. Bulk-query exports can therefore silently corrupt text fields or entirely lose datetime columns, so conversion needs to be schema-aware or the CSV values should remain strings.Useful? React with 👍 / 👎.