Photo: one async method per EXIF field (closes #148) #149

Merged
clawbot merged 2 commits from issue-148-exif-field-methods into next 2026-10-02 00:09:24 +02:00
Collaborator

Implements #148, following the plan in #148 (comment).

Photo gains thirteen async methods, one per PhotoExif field and named after it: make(), model(), lensModel(), dateTimeOriginal(), offsetTimeOriginal(), exposureTime(), fNumber(), iso(), focalLength(), orientation(), gpsLatitude(), gpsLongitude() and gpsAltitude(). Each takes the same optional opts as exif(), calls it, and returns that one field, typed by the field itself, so undefined when the file lacks it. exif() is unchanged.

Photo implements a type built from PhotoExif's keys, with one such method per field, so the build's type check fails when PhotoExif has a field Photo has no method for, whatever the test fixtures hold.

A new test, run once on the JPEG fixture and once on test/exif.heic, checks that each method gives the same value as exif(). The test for an original that is not an image also checks that a method gives undefined. README and TODO.md list the methods.

What the diff does not show:

  • Each call reads the original again, from the save path or the cache. Nothing is kept between calls, so a caller that wants several fields should call exif() once.
  • The guard is in the type check, which make build and the CI build run; make check does not type-check.

Judgement call: the new test compares both files against heicFields, since the JPEG fixture holds the same values as the HEIC.

Model: opus-5-5

Implements https://git.eeqj.de/sneak/quak/issues/148, following the plan in https://git.eeqj.de/sneak/quak/issues/148#issuecomment-108451. `Photo` gains thirteen async methods, one per `PhotoExif` field and named after it: `make()`, `model()`, `lensModel()`, `dateTimeOriginal()`, `offsetTimeOriginal()`, `exposureTime()`, `fNumber()`, `iso()`, `focalLength()`, `orientation()`, `gpsLatitude()`, `gpsLongitude()` and `gpsAltitude()`. Each takes the same optional `opts` as `exif()`, calls it, and returns that one field, typed by the field itself, so `undefined` when the file lacks it. `exif()` is unchanged. `Photo` implements a type built from `PhotoExif`'s keys, with one such method per field, so the build's type check fails when `PhotoExif` has a field `Photo` has no method for, whatever the test fixtures hold. A new test, run once on the JPEG fixture and once on `test/exif.heic`, checks that each method gives the same value as `exif()`. The test for an original that is not an image also checks that a method gives `undefined`. README and `TODO.md` list the methods. What the diff does not show: - Each call reads the original again, from the save path or the cache. Nothing is kept between calls, so a caller that wants several fields should call `exif()` once. - The guard is in the type check, which `make build` and the CI build run; `make check` does not type-check. Judgement call: the new test compares both files against `heicFields`, since the JPEG fixture holds the same values as the HEIC. Model: opus-5-5
clawbot added the needs-review label 2026-10-01 22:44:48 +02:00
clawbot self-assigned this 2026-10-01 22:44:48 +02:00
Author
Collaborator

Review: fail.

  • test/library/content-library.test.ts:465, with src/library/read.ts:144: the check that every PhotoExif field has a method only sees fields the two fixtures hold. A field added to PhotoExif and readPhotoExif that the fixtures lack, with no method on Photo, passes every check, so exif() and the methods can drift apart. #148 rules that out ("one shared source of truth ... cannot drift apart"), and the plan says such a field fails the gate. The keyof PhotoExif cast in the test does not help, because test files are not type-checked. Acceptable: a check that fails whenever PhotoExif has a field Photo has no method for, whatever the fixtures hold. For example, Photo can declare that it implements a mapped type over PhotoExif's keys, each member a method taking opts and returning that field's type, which the build's type check enforces. The PR body, TODO.md and the test comment should then describe that guard.

Model: opus-5-5

Review: fail. - `test/library/content-library.test.ts:465`, with `src/library/read.ts:144`: the check that every `PhotoExif` field has a method only sees fields the two fixtures hold. A field added to `PhotoExif` and `readPhotoExif` that the fixtures lack, with no method on `Photo`, passes every check, so `exif()` and the methods can drift apart. https://git.eeqj.de/sneak/quak/issues/148 rules that out ("one shared source of truth ... cannot drift apart"), and the plan says such a field fails the gate. The `keyof PhotoExif` cast in the test does not help, because test files are not type-checked. Acceptable: a check that fails whenever `PhotoExif` has a field `Photo` has no method for, whatever the fixtures hold. For example, `Photo` can declare that it implements a mapped type over `PhotoExif`'s keys, each member a method taking `opts` and returning that field's type, which the build's type check enforces. The PR body, `TODO.md` and the test comment should then describe that guard. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-01 23:04:59 +02:00
clawbot added needs-review and removed needs-rework labels 2026-10-01 23:11:24 +02:00
clawbot added needs-rebase and removed needs-review labels 2026-10-01 23:22:24 +02:00
clawbot added 2 commits 2026-10-01 23:30:47 +02:00
Thirteen methods on Photo, make() through gpsAltitude(), each named after
its PhotoExif field and typed by it. Each calls exif() with the same opts
and returns that one field, or undefined when the file lacks it. A test
checks, on the JPEG fixture and on test/exif.heic, that every field
exif() returns has a method giving the same value. README and TODO.md
list them.

Model: opus-5-5
Photo implements one method per PhotoExif field
check / check (push) Successful in 1m22s
1ede66e5c0
Photo now implements a mapped type with one method per PhotoExif field,
each taking exif()'s options and giving that field's type, so the
build's type check fails when PhotoExif has a field Photo has no method
for, whatever the test fixtures hold. The test comment and TODO.md say
so.

Model: opus-5-5
clawbot force-pushed issue-148-exif-field-methods from 4986ebd889 to 1ede66e5c0 2026-10-01 23:30:47 +02:00 Compare
clawbot added needs-review and removed needs-rebase labels 2026-10-01 23:30:49 +02:00
Author
Collaborator

Review: pass.

Model: opus-5-5

Review: pass. Model: opus-5-5
clawbot merged commit d40f339c0b into next 2026-10-02 00:09:24 +02:00
clawbot deleted branch issue-148-exif-field-methods 2026-10-02 00:09:25 +02:00
Sign in to join this conversation.