Skip to content

Commit 9d12b68

Browse files
committed
chore: pin the #14938 fake-engine double, and add the changeset
check:engine-double-contract requires every findOne/update/delete fake engine double in a test file to be registered in the pinned, shrink-only ledger. The new #14938 pin test carries one; `--write` recorded its three verb rows — 3 added or grown, 0 lost — and nothing else moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
1 parent 810751c commit 9d12b68

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@objectstack/metadata-protocol': patch
3+
---
4+
5+
`SysMetadataRepository.listDrafts` emits the ISO-8601 string its own signature declares for `updatedAt`
6+
7+
`listDrafts` declares `updatedAt: string | null` on an inline TypeScript return type and reached the field through `row.updated_at ?? row.created_at ?? null`. `??` fires only on nullish, so the JS `Date` that Postgres and MySQL materialise for the builtin audit columns walked straight past it into a field the declaration calls a string. Driven through the published door, the pre-fix build answered `typeof "object"` and the visible text `Wed Mar 04 2026 05:06:07 GMT+0000 (Coordinated Universal Time)` where the same build's `dist/index.d.ts` promised `string | null`; it now answers `2026-03-04T05:06:07.089Z`.
8+
9+
`updated_at` / `created_at` are builtin audit columns: `SqlDriver#formatOutput` repairs them (and folds declared `datetime` columns) only inside its `if (this.isSqlite)` arm, and `withPostgresCalendarDayAsText` leaves `timestamptz` / `timestamp` deliberately untouched because those are instants. Nothing reported the mismatch — the declaration is an inline return type rather than a Zod schema, so a schema search finds nothing, and `rows` is cast `as any[]` one line above the map, so tsc saw a `string` assignment that never happened.
10+
11+
Canonicalised at the producer through the same adapter boundary `rowToItem` already uses, with the terminal chosen per call site: `null` here, because the chain being replaced already ended in `?? null` and that is what "absent" already means to this projection's consumers. An Invalid `Date` — reachable on both live dialects — takes that same branch instead of raising. Already-canonical SQLite text passes through byte-identically, and `updatedBy` is unchanged: `updated_by` / `created_by` are `Field.lookup('sys_user')` string columns, which the dialect asymmetry never reaches.
12+
13+
No published declaration moves: `dist/index.d.ts` and `dist/index.d.cts` are byte-identical across the fix, which already declared `updatedAt: string | null` before it. A JavaScript consumer that read the raw value and called a `Date` method on it, or stringified it, sees the corrected shape.

scripts/engine-double-contract.pinned.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,21 @@
16161616
"verb": "update",
16171617
"pinned": 1
16181618
},
1619+
{
1620+
"file": "packages/metadata-protocol/src/sys-metadata-repository-14938-list-drafts-updated-at.test.ts",
1621+
"verb": "delete",
1622+
"pinned": 1
1623+
},
1624+
{
1625+
"file": "packages/metadata-protocol/src/sys-metadata-repository-14938-list-drafts-updated-at.test.ts",
1626+
"verb": "findOne",
1627+
"pinned": 1
1628+
},
1629+
{
1630+
"file": "packages/metadata-protocol/src/sys-metadata-repository-14938-list-drafts-updated-at.test.ts",
1631+
"verb": "update",
1632+
"pinned": 1
1633+
},
16191634
{
16201635
"file": "packages/metadata-protocol/src/sys-metadata-repository.contract.test.ts",
16211636
"verb": "delete",

0 commit comments

Comments
 (0)