refactor(sim): consolidate record guards + pure utils into @sim/utils#5061
Conversation
Add isRecordLike (loose, non-prototype-checked record guard) and sortObjectKeysDeep; relocate isPlainRecord (strict) and normalizeEmail into @sim/utils so they are reusable across apps and packages. Unit tests cover the loose-vs-strict distinction, deep key sorting, and email normalization.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview
Other: Copilot workflow JSON formatting uses shared Domain-specific normalizers and array-allowing guards called out in the PR description are intentionally unchanged. Reviewed by Cursor Bugbot for commit 3cbf4c7. Configure here. |
Greptile SummaryThis PR consolidates a widespread pattern of locally-duplicated record guard predicates and pure utility functions into the
Confidence Score: 5/5This is a mechanical deduplication refactor with no functional changes — every replaced predicate and transform is semantically identical to its canonical equivalent. All ~55 inline record-guard substitutions replace predicates logically equivalent to isRecordLike. Boolean(v) and v !== null produce identical results for objects. isPlainRecord is a straight move with unchanged prototype logic. sortObjectKeysDeep is byte-for-byte identical to the two local implementations it replaces. normalizeToken and normalizeEmail consolidations are exact copies. The package.json subpath exports for @sim/utils/object and @sim/utils/string are already in place. No files require special attention — the most complex migration sites (copilot/request/session/contract.ts and executor/utils/start-block.ts) were audited and found to be clean substitutions. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["@sim/utils/object"] -->|isRecordLike| B["55+ call sites across\ntools / copilot / triggers / lib"]
A -->|isPlainRecord| C["records.ts\nexecution-core.ts\nsubblocks.ts\nsubblock-migrations.ts\nuser-file-base64.server.ts"]
A -->|sortObjectKeysDeep| D["json-sanitizer.ts\nbuilders.ts"]
E["@sim/utils/string"] -->|normalizeEmail| F["invitations/core.ts\ninvitations/send.ts\nworkspace-invitations.ts\nroute handlers"]
G["triggers/utils/tokens.ts"] -->|normalizeToken| H["salesforce/utils.ts\nservicenow/utils.ts"]
style A fill:#4ade80,stroke:#16a34a
style E fill:#4ade80,stroke:#16a34a
style G fill:#86efac,stroke:#16a34a
Reviews (2): Last reviewed commit: "refactor(sim): consolidate record guards..." | Re-trigger Greptile |
…sim/utils Replace ~55 re-implemented loose record guards with the canonical @sim/utils isRecordLike (and one strict site with isPlainRecord), and dedupe three normalize clusters: sortObjectKeysDeep (sanitization + copilot builders), normalizeToken (salesforce + servicenow triggers), and normalizeEmail. Array-allowing guards and domain-specific normalizers are intentionally left untouched. Pure refactor — identical predicates and transforms, no behavior change.
69ad368 to
3cbf4c7
Compare
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 3cbf4c7. Configure here.
Summary
@sim/utils:isRecordLike(loose),sortObjectKeysDeep; relocateisPlainRecord(strict) andnormalizeEmailso they're reusable across apps and packages.typeof === 'object' && !== null && !Array.isArray) across tools/providers/lib/workflows/copilot/triggers/contracts with the singleisRecordLike; one strict site →isPlainRecord.normalize*clusters:sortObjectKeysDeep(sanitization + copilot builders),normalizeToken(salesforce + servicenow triggers),normalizeEmail.comparison/normalize.ts, copilot persisted-message, vanta, SSO/domain) — migrating those would change behavior.Type of Change
Testing
@sim/utilsunit tests: loose-vs-strict guard distinction (Date/class-instance → loosetrue, strictfalse), deep key sort, email normalization.check:api-validation:strict+ monorepo-boundary checks pass.origin/staging— every migrated predicate/transform is an exact semantic no-op; the one risky union-narrowing site (lib/table/sql.ts) was deliberately skipped.Checklist