Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { describe, expect, test } from 'vitest';
import { formatVal } from '../format-value';

describe('formatVal', () => {
test('formats boolean values as visible text', () => {
expect(formatVal(true)).toBe('true');
expect(formatVal(false)).toBe('false');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { isObject } from 'lodash';

export function formatVal(data: any, pretty?: boolean): string {
if (isObject(data)) {
return JSON.stringify(data, null, pretty ? 2 : undefined);
Comment on lines +3 to +5

@coderabbitai coderabbitai Bot Aug 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 6 '\bformatVal\s*\(' client/packages/components/src/components/explorer

Repository: instantdb/instant

Length of output: 7391


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate file =="
cat -n client/packages/components/src/components/explorer/format-value.ts

echo "== explorer data typing/search =="
rg -n -C 4 'info\.row\.original\[attr\.name\]|\brow\.original\b|interface .*Raw|type .*Raw|data.*JSON|fromJSON|Json|Date|function' client/packages/components/src/components/explorer/inner-explorer.tsx client/packages/components/src/components/explorer/table-components.tsx | head -n 240

echo "== tests =="
cat -n client/packages/components/src/components/explorer/__tests__/format-value.test.ts

Repository: instantdb/instant

Length of output: 20093


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== rows type construction =="
rg -n -C 8 "itemsRes\.data|fallbackItems|Record<string, any>|itemsRes|QueryData|queryItems|fetch.*items|attributes|checkedDataType" client/packages/components/src/components/explorer/inner-explorer.tsx | head -n 220

echo "== possible row.original construction in repo =="
rg -n -C 5 'row\.original|info\.row\.original|row_original|original:' client/packages/components/src/components/explorer | head -n 200

echo "== lockfile package versions =="
fd -a 'package-lock\.json$|pnpm-lock\.yaml$|yarn\.lock$|bun\.lockb$' . | sed 's#^\./##' | head -n 20

Repository: instantdb/instant

Length of output: 12197


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== useNamespacesQuery references =="
rg -n -C 8 'function useNamespacesQuery|const useNamespacesQuery|export .*useNamespacesQuery|useNamespacesQuery\s*=' . | head -n 240

echo "== JS behavioral probe for formatVal contract edge case =="
node - <<'JS'
const isObjectLike = (value) => typeof value === 'object' && value <> null;
const isPlainObject = isObjectLike;
const isArray = Array.isArray;
const getTag = (value) => Object.prototype.toString.call(value);
const isFunction = (value) => typeof value === 'function';
const isObject = (value) => {
  const type = typeof value;
  return value !== null && (type === 'object' || type === 'function');
};
function stringifyProxy(data) {
  try { return JSON.stringify(data); } catch (e) { console.error('JSON.stringify proxy', e.name, e.message); return undefined; }
}
console.log('lodash-style object guard:', isObject(String), isObject(() => {}), isObject({}));
console.log('function stringify:', JSON.stringify(String), JSON.stringify(() => {}));
console.log('object stringify:', JSON.stringify({}));
console.log('proxy:', stringifyProxy(new Proxy({}, {})));
JS

Repository: instantdb/instant

Length of output: 2223


Ensure formatVal only formats JSON-compatible values.

formatVal(data, pretty) passes directly from explorer row values after explicit ref/date handling. If an attribute contains a function-like object, JSON.stringify returns undefined while the return type says string; add a plain/object-type check or a defined fallback.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/packages/components/src/components/explorer/format-value.ts` around
lines 3 - 5, Update formatVal so JSON.stringify results are guaranteed to be a
string when handling objects, including function-like or otherwise
non-JSON-compatible values. Add an appropriate plain/object-type validation or
use a defined string fallback while preserving the existing pretty-print
behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is same behavior as before

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nezaj, correct. This PR preserves the existing JSON.stringify behavior for object values. It only centralizes the formatter and adds boolean rendering. The Comment images confirm that true now displays in the Explorer.

I will withdraw this comment.

You are interacting with an AI system.

}

return String(data);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import { isObject } from 'lodash';
import { EditNamespaceDialog } from './edit-namespace-dialog';
import { EditRowDialog, isEditableExplorerAttr } from './edit-row-dialog';
import copy from 'copy-to-clipboard';
import { formatVal } from './format-value';

const fallbackItems: any[] = [];

Expand Down Expand Up @@ -539,10 +540,7 @@ export const InnerExplorer: React.FC<{
return info.row.original[attr.name];
}
}
if (isObject(info.row.original[attr.name])) {
return <Val data={info.row.original[attr.name]}></Val>;
}
return info.row.original[attr.name];
return formatVal(info.row.original[attr.name]);
},
});
});
Expand Down Expand Up @@ -1469,14 +1467,6 @@ export const InnerExplorer: React.FC<{
);
};

function formatVal(data: any, pretty?: boolean): string {
if (isObject(data)) {
return JSON.stringify(data, null, pretty ? 2 : undefined);
}

return String(data);
}

function Val({ data, pretty }: { data: any; pretty?: boolean }) {
const props = useExplorerProps();
const sanitized = formatVal(data, pretty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { isObject } from 'lodash';
import copy from 'copy-to-clipboard';
import { useExplorerDialog, useExplorerProps, useExplorerState } from '.';
import { TableColMeta } from './inner-explorer';
import { formatVal } from './format-value';

export const TableHeader = ({
header,
Expand Down Expand Up @@ -397,14 +398,6 @@ function isCopyableCellValue(
return true;
}

function formatVal(data: any, pretty?: boolean): string {
if (isObject(data)) {
return JSON.stringify(data, null, pretty ? 2 : undefined);
}

return String(data);
}

function Val({ data, pretty }: { data: any; pretty?: boolean }) {
const sanitized = formatVal(data, pretty);
const explorerProps = useExplorerProps();
Expand Down
2 changes: 1 addition & 1 deletion client/packages/version/src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// Update the version here and merge your code to main to
// publish a new version of all of the packages to npm.

const version = 'v1.0.58';
const version = 'v1.0.59';

export { version };
Loading