Skip to content

fix(template-function-uuid): use the current time when uuid.v6 has no timestamp - #647

Merged
gschier merged 2 commits into
mountain-loop:mainfrom
NgoQuocViet2001:fix-uuid-v6-default-timestamp
Sep 15, 2026
Merged

gschier merged 2 commits into
mountain-loop:mainfrom
NgoQuocViet2001:fix-uuid-v6-default-timestamp

Conversation

@NgoQuocViet2001

Copy link
Copy Markdown
Contributor

Summary

uuid.v6() with its optional timestamp left empty renders a zeroed timestamp — 00000000-0000-6000-…, i.e. 1582-10-15 — instead of the current time. Fall back to the uuid package's own clock when no parseable timestamp is given.

Submission

  • This PR is a bug fix.
  • If this PR is not a bug fix, I linked the feedback item where @gschier explicitly gave me permission to work on it.
  • I have read and followed CONTRIBUTING.md.
  • I tested this change locally.
  • I added or updated tests, or tests are not reasonable for this change.
  • I added screenshots or recordings, or this change does not affect the UI.

Detail

The timestamp argument is optional: true, but onRender always does:

return v6({ msecs: new Date(String(args.values.timestamp)).getTime() });

With nothing supplied, String(undefined) is "undefined", new Date("undefined").getTime() is NaN, and NaN is not undefined — so the uuid package does not fall back to Date.now(). It runs NaN through its bit-packing, where every masked field comes out zero.

Running the plugin's own onRender and decoding the timestamp each result carries:

no timestamp arg   00000000-0000-6000-8ade-ddfd6bafa3a7   embedded time 1582-10-15T00:00:00.000Z
timestamp: ""      00000000-0000-6000-9c93-81a4d423b915   embedded time 1582-10-15T00:00:00.000Z
timestamp: null    00000000-0000-6000-a963-fd5a281d29d3   embedded time 1582-10-15T00:00:00.000Z
timestamp given    1f03bb4f-e97d-6200-8c5d-715f23ffe82c   embedded time 2025-05-28T11:15:00.000Z

The template renderer only inserts arguments that literally appear in the tag, so the plain ${[ uuid.v6() ]} reaches the plugin with no timestamp at all — the default usage is the broken one. v6 exists to be time-sortable, and these all share one fixed timestamp, so consecutive values no longer sort by generation.

After the change the first three embed the current time, and a supplied timestamp is unchanged.

An unparseable non-empty timestamp also falls back to the clock rather than silently producing the 1582 value. If you would prefer that case to surface an error instead, that is a one-line change.

Test plan

  • Added plugins/template-function-uuid/tests/uuid.test.ts — the plugin had no tests — following the template-function-regex pattern (vite-plus/test, onRender({} as Context, { values, purpose: "send" })). It decodes the embedded timestamp and asserts it falls between the times read before and after the call, for {}, "" and null, and that a given timestamp is embedded exactly.
  • Checked: the same assertions fail for all three empty cases on unmodified main, and pass with the change.

… timestamp

The timestamp argument is optional, but onRender always passed
new Date(String(args.values.timestamp)).getTime() as msecs. With nothing
supplied that is new Date("undefined") -- NaN -- and the uuid package does
not treat NaN as absent: it masks it down to a zero timestamp. Every default
uuid.v6() therefore rendered as 00000000-0000-6000-..., embedding
1582-10-15 instead of now, so consecutive UUIDs no longer sort by generation.

Only pass msecs when the value parses; otherwise let v6() use its own clock.
@github-actions github-actions Bot added the contribution: in scope Community PR appears to be in scope for maintainer review. label Sep 14, 2026
@github-actions

Copy link
Copy Markdown

Thanks for the PR. This appears to match Yaak's contribution policy and is awaiting review by @gschier.

This only means the PR is in scope for review. It does not mean the change has been reviewed or accepted for merge.

@github-actions
github-actions Bot requested a review from gschier September 14, 2026 05:25
@greptile-apps

greptile-apps Bot commented Sep 14, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the timestamp fallback correctly implemented and covered by tests.

Summary

  • Preserves explicitly supplied, valid timestamps.
  • Adds timestamp-decoding tests for fallback and valid-input behavior.
  • The previously requested malformed-input coverage is now present.

Reviews (2) · Last reviewed commit: "test(template-function-uuid): cover an u..."

Comment thread plugins/template-function-uuid/tests/uuid.test.ts

@gschier gschier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thansk for the fix!

@gschier
gschier merged commit 3098182 into mountain-loop:main Sep 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution: in scope Community PR appears to be in scope for maintainer review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants