Skip to content

feat(modifiers): add AutoDateModifier with CreationTime and UpdateTime decorators - #11

Merged
Upd4ting merged 2 commits into
mainfrom
feat/autodate-modifier
Jul 15, 2026
Merged

feat(modifiers): add AutoDateModifier with CreationTime and UpdateTime decorators#11
Upd4ting merged 2 commits into
mainfrom
feat/autodate-modifier

Conversation

@Upd4ting

@Upd4ting Upd4ting commented Jul 15, 2026

Copy link
Copy Markdown
Member

🔗 Linked issue

N/A

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Moves the automatic timestamp modifier from the CMS cms-base interface (AntelopeJS/cms) into the shared modifiers, so any table definition can use it without depending on the CMS.

  • Adds AutoDateModifier, an event-only modifier (no Table.with() mixin required) that populates timestamp fields through the insert/update modifier events.
  • Adds the CreationTime decorator: field set to the current date on insert, removed from update payloads so the original creation date is preserved.
  • Adds the UpdateTime decorator: field refreshed with the current date on both insert and update.
  • Exposes the new ./modifiers/autodate subpath in package.json exports and typesVersions.
  • Documents the new modifier in docs/3.table-modifiers.md.

Follow-up PRs update the consumers (cms, cms-api, cms-saas) to import these decorators from this package. Behavior is identical to the CMS implementation.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Test plan

  • pnpm test — new Modifiers - autodate suite covers insert/update behavior for both decorator types, including the decorator-through-events integration path (101 tests passing).

Greptile Summary

This PR extracts the automatic timestamp modifier from cms-base into the shared interface-database-decorators package, making CreationTime and UpdateTime decorators available to any table definition without a CMS dependency. The implementation is clean, event-driven, and behaviorally identical to the original CMS implementation.

  • Adds AutoDateModifier (event-only, no Table.with() mixin required) with insert/update handlers that set or remove timestamp fields.
  • Exposes CreationTime and UpdateTime decorators via a new ./modifiers/autodate subpath in package.json exports and typesVersions.
  • Adds a test suite with six cases covering unit-level modifier behavior, decorator-through-events integration, and the toDatabase payload verification that confirms createdAt is absent from update payloads.

Confidence Score: 5/5

Safe to merge — the change is a straightforward extraction of well-understood CMS logic into a shared location with no behavioral changes.

The modifier is event-only with two simple methods. The package export wiring matches the existing pattern exactly. The test suite covers all paths including the toDatabase payload shape. No regressions are introduced.

No files require special attention.

Important Files Changed

Filename Overview
src/modifiers/autodate.ts New event-only modifier with insert/update handlers; correctly typed options, clean decorator factories, no issues found.
src/tests/modifiers/autodate.test.ts Comprehensive six-case test suite covering unit behavior, events integration, and toDatabase payload verification; all scenarios are well-covered.
package.json Adds ./modifiers/autodate export entry and typesVersions mapping, consistent with the existing patterns for other modifiers.
src/modifiers/index.ts Adds re-export of the autodate module; ordering is alphabetically consistent.
docs/3.table-modifiers.md New AutoDateModifier section is accurate, concise, and clearly describes the event-only behavior; no inaccuracies found.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant triggerEvent
    participant AutoDateModifier
    participant Object

    Note over Caller,Object: Insert flow
    Caller->>triggerEvent: triggerEvent(instance, "insert")
    triggerEvent->>AutoDateModifier: insert(object, "createdAt")
    AutoDateModifier->>Object: "object["createdAt"] = new Date()"
    triggerEvent->>AutoDateModifier: insert(object, "updatedAt")
    AutoDateModifier->>Object: "object["updatedAt"] = new Date()"

    Note over Caller,Object: Update flow
    Caller->>triggerEvent: triggerEvent(instance, "update")
    triggerEvent->>AutoDateModifier: "update(object, "createdAt") [type=created]"
    AutoDateModifier->>Object: delete object["createdAt"]
    triggerEvent->>AutoDateModifier: "update(object, "updatedAt") [type=updated]"
    AutoDateModifier->>Object: "object["updatedAt"] = new Date()"

    Note over Caller,Object: Serialize
    Caller->>Object: toDatabase(instance)
    Object-->>Caller: "{ updatedAt: Date } (no createdAt)"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant triggerEvent
    participant AutoDateModifier
    participant Object

    Note over Caller,Object: Insert flow
    Caller->>triggerEvent: triggerEvent(instance, "insert")
    triggerEvent->>AutoDateModifier: insert(object, "createdAt")
    AutoDateModifier->>Object: "object["createdAt"] = new Date()"
    triggerEvent->>AutoDateModifier: insert(object, "updatedAt")
    AutoDateModifier->>Object: "object["updatedAt"] = new Date()"

    Note over Caller,Object: Update flow
    Caller->>triggerEvent: triggerEvent(instance, "update")
    triggerEvent->>AutoDateModifier: "update(object, "createdAt") [type=created]"
    AutoDateModifier->>Object: delete object["createdAt"]
    triggerEvent->>AutoDateModifier: "update(object, "updatedAt") [type=updated]"
    AutoDateModifier->>Object: "object["updatedAt"] = new Date()"

    Note over Caller,Object: Serialize
    Caller->>Object: toDatabase(instance)
    Object-->>Caller: "{ updatedAt: Date } (no createdAt)"
Loading

Reviews (3): Last reviewed commit: "test(modifiers): assert autodate behavio..." | Re-trigger Greptile

…e decorators

Move the automatic timestamp modifier from the CMS cms-base interface
into the shared modifiers so any table definition can use it. Fields
marked with CreationTime are set on insert and preserved on update,
while UpdateTime fields are refreshed on every write.
Comment thread src/modifiers/autodate.ts
Comment thread src/modifiers/autodate.ts
Comment thread src/tests/modifiers/autodate.test.ts
@Upd4ting

Copy link
Copy Markdown
Member Author

@greptile review

Address greptile review feedback: verify through toDatabase that update
payloads omit CreationTime fields and refresh UpdateTime fields.
@Upd4ting

Copy link
Copy Markdown
Member Author

@greptile review

@Upd4ting
Upd4ting merged commit e2b230b into main Jul 15, 2026
3 checks passed
@Upd4ting
Upd4ting deleted the feat/autodate-modifier branch July 15, 2026 13:54
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