Version
auth0-deploy-cli 8.42.0, and present on main at the time of writing.
What happens
When a dry run finds an array item present on one side only, the diff log records the item as [object Object]:
Array length difference for [acme.connections]: local:1 vs remote:0
Array item difference at [acme.connections[0]]: local:[object Object] vs remote:undefined
The message carries no information about which item would be added or removed, which for organization connections is the entire content of the change. The same strings are what --dry-run --interactive writes to dry-run-diff-log.json, so a machine-readable log of an object-array change is unusable as well.
Reproduction
const {
getObjectDifferences,
} = require('auth0-deploy-cli/lib/tools/calculateDryRunChanges');
getObjectDifferences(
{ connections: [{ connection_id: 'con_abc', assign_membership_on_login: false }] },
{ connections: [] },
'acme',
'organizations'
);
// [
// 'Array length difference for [acme.connections]: local:1 vs remote:0',
// 'Array item difference at [acme.connections[0]]: local:[object Object] vs remote:undefined'
// ]
Root cause
The message is built by template-literal interpolation, which calls Object.prototype.toString on an object item:
// src/tools/calculateDryRunChanges.ts:235
const message = `Array item difference at [${currentPath}[${index}]]: local:${item} vs remote:${normalizedRemoteValue[index]}`;
The else if at line 234 is reached exactly when one of the two sides is not an object: an added or removed element, or a mixed-type array. The object-vs-object case recurses at line 226 and is fine.
Note the diff log stores formatted strings rather than the values, so the information is not recoverable downstream: by the time anything reads getDiffLog() or dry-run-diff-log.json, the object is gone.
Expected
The added or removed item is rendered as something a reader can act on, for example:
Array item difference at [acme.connections[0]]: local:{"assign_membership_on_login":false,"connection_id":"con_abc"} vs remote:undefined
Suggested fix
Serialize non-primitives instead of interpolating them:
const format = (value: unknown): string =>
typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);
const message = `Array item difference at [${currentPath}[${index}]]: local:${format(
item
)} vs remote:${format(normalizedRemoteValue[index])}`;
A length cap would be reasonable if unbounded items are a concern.
Related: #1451 - both are in the handling of object arrays in getObjectDifferences, but they are independent, and this one is cosmetic next to that one.
Version
auth0-deploy-cli8.42.0, and present onmainat the time of writing.What happens
When a dry run finds an array item present on one side only, the diff log records the item as
[object Object]:The message carries no information about which item would be added or removed, which for organization connections is the entire content of the change. The same strings are what
--dry-run --interactivewrites todry-run-diff-log.json, so a machine-readable log of an object-array change is unusable as well.Reproduction
Root cause
The message is built by template-literal interpolation, which calls
Object.prototype.toStringon an object item:The
else ifat line 234 is reached exactly when one of the two sides is not an object: an added or removed element, or a mixed-type array. The object-vs-object case recurses at line 226 and is fine.Note the diff log stores formatted strings rather than the values, so the information is not recoverable downstream: by the time anything reads
getDiffLog()ordry-run-diff-log.json, the object is gone.Expected
The added or removed item is rendered as something a reader can act on, for example:
Suggested fix
Serialize non-primitives instead of interpolating them:
A length cap would be reasonable if unbounded items are a concern.
Related: #1451 - both are in the handling of object arrays in
getObjectDifferences, but they are independent, and this one is cosmetic next to that one.