Skip to content

Extract shared type guards and schema type from formatters#46

Merged
devxoul merged 3 commits intomainfrom
refactor/shared-formatter-types
Mar 10, 2026
Merged

Extract shared type guards and schema type from formatters#46
devxoul merged 3 commits intomainfrom
refactor/shared-formatter-types

Conversation

@devxoul
Copy link
Owner

@devxoul devxoul commented Mar 10, 2026

Summary

Extract duplicated type definitions and type-guard utility functions from both platform formatter files into shared modules. Both notion/formatters.ts and notionbot/formatters.ts defined identical (or near-identical) helpers for narrowing unknown values — these now live in src/shared/ and are imported by both platforms.

Changes

New shared modules

File Content
src/shared/types/schema.ts SimplifiedSchemaProperty type — was defined identically in both formatter files.
src/shared/utils/type-guards.ts toRecord, toRecordOrNull, toStringValue/toStringOrEmpty, toOptionalString/toCursor, toStringArray — unified type-guard helpers with separate exports to preserve null vs undefined return type differences.

Formatter updates

File Change
src/platforms/notion/formatters.ts Remove 4 inline helper functions (toRecord, toStringArray, toStringValue, toOptionalString) and the SimplifiedSchemaProperty type definition. Import all from shared modules.
src/platforms/notionbot/formatters.ts Remove 3 inline helper functions (toRecord, toStringOrEmpty, toCursor) and the SimplifiedSchemaProperty type definition. Import from shared modules, aliasing toRecordOrNull as toRecord to preserve the null-returning contract without changing call sites.

Context

The two platform formatters evolved independently, each accumulating their own toRecord, toString*, and SimplifiedSchemaProperty definitions. The implementations were functionally identical but differed in return types (undefined vs null) — a consequence of the unofficial API using undefined and the official API using null for absent values. The shared module preserves both contracts via toRecord (returns undefined) and toRecordOrNull (returns null), so no call-site changes are needed.

Testing

All 599 tests pass, typecheck clean. No behavioral changes — pure refactor.


Summary by cubic

Extracted shared type guards and the SimplifiedSchemaProperty type to src/shared and updated both Notion formatters to use them. Removes duplication and preserves null vs undefined return contracts; no behavior changes.

  • Refactors
    • Moved SimplifiedSchemaProperty to src/shared/types/schema.ts.
    • Added src/shared/utils/type-guards.ts with toRecord/toRecordOrNull (both ignore arrays), toStringValue/toStringOrEmpty, toOptionalString/toCursor, toStringArray.
    • Updated notion/formatters.ts and notionbot/formatters.ts to import shared helpers; in NotionBot, aliased toRecordOrNull as toRecord to keep the null contract.

Written for commit 0c39d90. Summary will update on new commits.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/shared/utils/type-guards.ts">

<violation number="1" location="src/shared/utils/type-guards.ts:14">
P2: `toRecordOrNull` accepts arrays as records; add the same `Array.isArray` exclusion used by `toRecord` to keep object-guard behavior consistent.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@devxoul devxoul merged commit 5ed7912 into main Mar 10, 2026
2 checks passed
@devxoul devxoul deleted the refactor/shared-formatter-types branch March 10, 2026 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant