fix(schema-org): allow null to opt out of default values#680
Conversation
When a user sets a schema-org property to null, it is now removed from the final output instead of being overwritten by setIfEmpty defaults or inheritMeta. null acts as an explicit opt-out sentinel that is preserved through the full resolution pipeline and stripped only after all resolvers (including resolveRootNode) have run. Closes #548
|
No actionable comments were generated in the recent review. π βΉοΈ Recent review infoβοΈ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: π Files selected for processing (1)
π§ Files skipped from review as they are similar to previous changes (1)
π WalkthroughWalkthroughThis change preserves explicit nulls during resolution so resolvers can observe them to opt out of defaults, then removes Changes
Sequence Diagram(s)sequenceDiagram
participant Injector as Graph Injector
participant Resolver as resolveRootNode (resolvers)
participant Nodes as Nodes (ctx.nodes)
participant Utils as stripNullProperties
participant Normalizer as Final Normalization
Injector->>Resolver: Call resolveRootNode for each root node
Resolver->>Nodes: Read node properties (nulls preserved)
Resolver-->>Injector: Return resolved node (may rely on null sentinels)
Injector->>Nodes: Delete `_resolver` from all nodes (after all resolves)
Injector->>Utils: Call stripNullProperties on nodes
Utils->>Nodes: Recursively remove `null` properties
Injector->>Normalizer: Pass cleaned nodes for final normalization
Estimated code review effortπ― 3 (Moderate) | β±οΈ ~20 minutes Poem
π₯ Pre-merge checks | β 4 | β 1β Failed checks (1 warning)
β Passed checks (4 passed)
βοΈ Tip: You can configure your own custom pre-merge checks in the settings. β¨ Finishing Touches
π§ͺ Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bundle Size Analysis
|
There was a problem hiding this comment.
Actionable comments posted: 2
π§Ή Nitpick comments (1)
packages/schema-org/src/utils/index.ts (1)
54-56:setIfEmptystill drops valid falsy defaults.The function now respects
nullon the destination side, but Line 55 still skips injecting0,false, and''because the RHS guard relies on truthiness. To distinguish only "undefined" from "explicitly provided", consider:β»οΈ Proposed refactor
export function setIfEmpty<T extends Thing>(node: T, field: keyof T, value: any) { - if (node?.[field] === undefined && value) + if (node?.[field] === undefined && value != null) node[field] = value }π€ Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/schema-org/src/utils/index.ts` around lines 54 - 56, The setIfEmpty function currently avoids setting defaults when the provided value is falsy (0, false, ''), because the RHS uses truthiness; update the conditional in setIfEmpty so it only treats undefined as "no value" (i.e., check value !== undefined) while still requiring the destination to be undefined (node?.[field] === undefined). Modify the logic in the setIfEmpty function to use the explicit undefined check for the incoming value so explicit falsy defaults are assigned.
π€ Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/schema-org/src/core/graph.ts`:
- Around line 125-131: The null-sentinel stripping (stripNullProperties) and
removal of node._resolver are happening per-node immediately after calling
node._resolver.resolveRootNode, which makes pass-2 resolvers see earlier nodes
with sentinels already erased; instead, defer calling stripNullProperties(node)
and delete node._resolver until after the entire second-pass resolution loop
completes (i.e., run resolveRootNode for every node first using
node._resolver.resolveRootNode(node, ctx) / ctx.find(), then in a subsequent
loop call stripNullProperties(node) and delete node._resolver for each node), so
all resolveRootNode handlers can observe null opt-out sentinels consistently.
In `@packages/schema-org/src/utils/index.ts`:
- Around line 164-177: The stripNullProperties function currently uses delete on
numeric keys which creates sparse arrays (holes) that JSON.stringify turns into
nulls; update stripNullProperties to detect arrays (Array.isArray(v)) and for
arrays remove null entries by constructing a new filtered array (e.g., v =
v.filter(el => el !== null)) or splice out nulls, then recurse into each
remaining element (calling stripNullProperties on object elements) instead of
deleting numeric indices; keep the existing __v_isReadonly and __v_isRef checks
and apply them to array elements as well, and assign the filtered array back to
obj[k] so callers of stripNullProperties (the function name) see a compact array
rather than a sparse one.
---
Nitpick comments:
In `@packages/schema-org/src/utils/index.ts`:
- Around line 54-56: The setIfEmpty function currently avoids setting defaults
when the provided value is falsy (0, false, ''), because the RHS uses
truthiness; update the conditional in setIfEmpty so it only treats undefined as
"no value" (i.e., check value !== undefined) while still requiring the
destination to be undefined (node?.[field] === undefined). Modify the logic in
the setIfEmpty function to use the explicit undefined check for the incoming
value so explicit falsy defaults are assigned.
βΉοΈ Review info
βοΈ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5da2e0eb-70a9-4087-9090-66f332491192
π Files selected for processing (3)
packages/schema-org/src/core/graph.tspackages/schema-org/src/nodes/Product/index.test.tspackages/schema-org/src/utils/index.ts
|
@copilot fix code rabbits issues |
|
@harlan-zw I've opened a new pull request, #687, to work on those changes. Once the pull request is ready, I'll request review from you. |
* Initial plan * fix(schema-org): address CodeRabbit issues with null opt-out implementation Co-authored-by: harlan-zw <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: harlan-zw <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 1
π€ Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/schema-org/src/core/graph.ts`:
- Around line 131-133: The loop currently calls
stripNullProperties(ctx.nodes[i]) before deleting ctx.nodes[i]._resolver, which
lets stripNullProperties traverse and mutate node._resolver; to fix, remove the
_resolver property before stripping by moving the delete into a prior pass or by
changing stripNullProperties to ignore the "_resolver" keyβupdate the code
touching ctx.nodes (reference: ctx.nodes array, stripNullProperties function,
and the "_resolver" property) so that deletion of _resolver occurs before any
stripping operation (or add logic in stripNullProperties to skip "_resolver").
βΉοΈ Review info
βοΈ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 21e742f6-c14a-430e-9e3d-99ab73e4ec7d
π Files selected for processing (2)
packages/schema-org/src/core/graph.tspackages/schema-org/src/utils/index.ts
π§ Files skipped from review as they are similar to previous changes (1)
- packages/schema-org/src/utils/index.ts
|
more issues @copilot |
|
@harlan-zw I've opened a new pull request, #688, to work on those changes. Once the pull request is ready, I'll request review from you. |
* Initial plan * fix(schema-org): delete _resolver before stripping null properties Co-authored-by: harlan-zw <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: harlan-zw <[email protected]>
π Linked issue
Resolves #548
β Type of change
π Description
Schema-org's
setIfEmptyalways injected defaults for properties likesku,priceValidUntil, andurl, with no way to opt out. Now, setting a property tonullexplicitly removes it from the output. ThesetIfEmptycheck was changed from falsy to=== undefined, and null stripping was split into a final pass after all resolvers run so the sentinel survives intermediate resolution.Summary by CodeRabbit
Bug Fixes
Tests
Chores