82 lines
3.1 KiB
Markdown
82 lines
3.1 KiB
Markdown
# F-060 — Implementer evidence
|
||
|
||
## Scope delivered
|
||
|
||
`scripts/generate-thumbnails.sh` was lagging behind the new resize contract
|
||
introduced by F-059. It used `sharp().resize({ width: size, withoutEnlargement: true })`
|
||
with no max-height cap, and it skipped already cached files. After F-059 the
|
||
on-demand path (upload route, dynamic `/uploads/[...path]/route.ts` in all
|
||
three apps) produces `fit: 'inside'` thumbnails bounded by `width * 1.4` height.
|
||
Running the batch script did nothing for existing files — which meant the
|
||
admin/frontend/storefront public uploads still held the legacy shape.
|
||
|
||
## Changes
|
||
|
||
### `project/scripts/generate-thumbnails.mjs`
|
||
|
||
Two adjustments to keep the batch script aligned with the on-demand path:
|
||
|
||
1. **Resize contract** — same `fit: 'inside'` and `MAX_HEIGHT_RATIO = 1.4`
|
||
bound as the upload route:
|
||
|
||
```js
|
||
const maxHeight = Math.round(size * MAX_HEIGHT_RATIO);
|
||
await sharp(src)
|
||
.resize({ width: size, height: maxHeight, fit: 'inside', withoutEnlargement: true })
|
||
.jpeg({ quality: 80 })
|
||
.toFile(thumbPath);
|
||
```
|
||
|
||
2. **`FORCE` flag** — `FORCE=1` (or `FORCE=true`) skips the cache-skip
|
||
logic, so the script can regenerate thumbnails in place without deleting
|
||
the existing files first. Default behaviour (skip existing) is preserved
|
||
for normal cron runs.
|
||
|
||
```bash
|
||
FORCE=1 ./scripts/generate-thumbnails.sh
|
||
```
|
||
|
||
## Acceptance traceability
|
||
|
||
| Acceptance criterion | How it is met |
|
||
| -------------------- | ------------- |
|
||
| Script uses `fit: 'inside'` with `maxHeight = size × 1.4` | Source updated, line-by-line equivalent to the upload route. |
|
||
| `FORCE` flag regenerates existing cached thumbnails | New env var read at startup, controls the skip block. |
|
||
| All cached thumbnails now use the new bounded-box behaviour matching upload route | After `FORCE=1 ./scripts/generate-thumbnails.sh`: 42 thumbnails regenerated (7 images × 2 sizes × 3 apps). On-disk dimensions verified with `file`. |
|
||
| Non-square source thumbnails are not cropped | 600×800 source produces 40×53 and 200×267 (aspect 3:4 preserved). 800×800 source produces 40×40 and 200×200. 1×1 sources stay 1×1 (`withoutEnlargement` is intentional). |
|
||
| `verify.sh` is green | Exit 0. |
|
||
|
||
## Manual verification
|
||
|
||
```
|
||
$ FORCE=1 ./scripts/generate-thumbnails.sh
|
||
[INFO] Found 7 source images
|
||
[OK] Processed 7 images, generated 42 new thumbnails
|
||
|
||
$ file project/{apps/admin,frontend,storefront}/public/uploads/40/*.jpg
|
||
… 2616a0de-… → 40x53
|
||
… 7f0a005a-… → 40x40
|
||
… 8223b962-… → 40x40
|
||
… a7e3aa30-… → 1x1 (source is 1x1; withoutEnlargement prevents upscale)
|
||
… bd8fe585-… → 40x40
|
||
… d04dc789-… → 1x1 (source is 1x1)
|
||
… fa7a31db-… → 40x53
|
||
```
|
||
|
||
```
|
||
$ curl /uploads/40/2616a0de-… | file -
|
||
/dev/stdin: JPEG image data, baseline, precision 8, 40x53, components 3
|
||
```
|
||
|
||
## Build verification
|
||
|
||
- `./scripts/verify.sh` — exit 0
|
||
- All four services restarted via `monolith.sh prod restart`, all 200
|
||
- `/uploads/40/...` and `/uploads/200/...` reachable from admin, frontend,
|
||
storefront (HTTP 200)
|
||
|
||
## Files touched
|
||
|
||
```
|
||
project/scripts/generate-thumbnails.mjs (modified)
|
||
``` |