@nitida/sdk 0.31.4 → 0.31.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -883,7 +883,20 @@ const asset = await aq.assets.byHash(sha256);
|
|
|
883
883
|
> outside `TransformWidth`. Need an arbitrary one? **Sign it** —
|
|
884
884
|
> `aq.transform(asset, { width: 1490 }, { sign: true })` and `getSignedTransformUrl` take
|
|
885
885
|
> `SignedTransformOptions` (where `width` widens to `number`); a valid `?sig=` earns the
|
|
886
|
-
> edge-whitelist bypass.
|
|
886
|
+
> edge-whitelist bypass.
|
|
887
|
+
>
|
|
888
|
+
> ⚠️ **Signed widths have two ceilings the edge does not announce** (measured
|
|
889
|
+
> 2026-08-24):
|
|
890
|
+
>
|
|
891
|
+
> 1. **7680 is the hard cap.** `7680` → 200, `7681` → 400. Unsigned, the real
|
|
892
|
+
> cap is 3840 — so `3841…4320` is a dead band the old 400 message called
|
|
893
|
+
> "in range", and `4321…7680` works signed while that message called it
|
|
894
|
+
> impossible.
|
|
895
|
+
> 2. **Above the source width it CLAMPS and still answers 200.** `/t/` never
|
|
896
|
+
> upscales. Ask for 5000 on an 800 px master and you get **800 px of bytes
|
|
897
|
+
> with HTTP 200** — no error, no warning. Read `x-transform-dsl` on the
|
|
898
|
+
> response (it names the width actually used) or size against the source, if
|
|
899
|
+
> the exact width matters. `transformSrcSet` / `getTransformSrcSet` deliberately keep
|
|
887
900
|
> `number[]` because a responsive ladder may legitimately include DPR-row widths (e.g.
|
|
888
901
|
> `2400`). `height` stays `number` — for the responsive path it's derived from `width`
|
|
889
902
|
> by aspect ratio; only fixed-canvas crops / `genfill` set it explicitly.
|
|
@@ -897,8 +910,14 @@ point of asking for `auto` instead of naming a format.
|
|
|
897
910
|
`gravity=face` detects the highest-confidence face and crops to it with
|
|
898
911
|
sensible padding (50 % of face dimensions on each side, clamped to source
|
|
899
912
|
bounds, keeping the requested aspect ratio). When no face is detected it
|
|
900
|
-
falls back to saliency-based cropping
|
|
901
|
-
`X-Transform-Face
|
|
913
|
+
falls back to saliency-based cropping. The response **always** carries
|
|
914
|
+
`X-Transform-Face`, with one of two values: **`matched`** when a face was found,
|
|
915
|
+
**`fallback`** when it saliency-cropped.
|
|
916
|
+
|
|
917
|
+
⚠️ Check the VALUE, not the presence. The header is emitted **only for
|
|
918
|
+
`gravity=face`** — with `center` or `auto` it is absent, and that absence does
|
|
919
|
+
not mean "no face". Code that tests for presence is right 0 % of the time on
|
|
920
|
+
photos that do contain a face. Cost to you:
|
|
902
921
|
~10 ms warm; ~150 ms on the first request after a cold start.
|
|
903
922
|
|
|
904
923
|
`quality=auto` adapts the per-format quality to source complexity
|
|
@@ -1186,6 +1205,18 @@ landscape source ✓). For bigger crops, prefer `gravity=auto` smart-crop,
|
|
|
1186
1205
|
which is deterministic and free — no generation, no invention.
|
|
1187
1206
|
|
|
1188
1207
|
**What it costs you: ~$0.05 for the first request** per (sha, dsl, format)
|
|
1208
|
+
⚠️ **The signature guards GENERATION, not DELIVERY.** Once a signed transform
|
|
1209
|
+
runs, its result is written to `/{tenant}/v/<sha>-t<dslHash>.<ext>` and served
|
|
1210
|
+
there **with HTTP 200 and no `?sig=`**. `<dslHash>` is `sha256(canonical DSL)`
|
|
1211
|
+
truncated to 16 — **no secret in it**, so anyone who guesses the DSL derives the
|
|
1212
|
+
URL. Measured: a signed `width=641` (unreachable unsigned) went from 404 to 200
|
|
1213
|
+
at the derived path after a single signed GET.
|
|
1214
|
+
|
|
1215
|
+
Two consequences worth planning around: turning on `strict_transforms` does not
|
|
1216
|
+
un-publish anything already generated, and for `genfill` — whose entire cost
|
|
1217
|
+
guard is the signature — the result you paid for stays publicly readable. Treat
|
|
1218
|
+
a signed transform as "pay once, publish forever", not as an access control.
|
|
1219
|
+
|
|
1189
1220
|
tuple. Subsequent identical requests are 302 redirects to the cached WebP —
|
|
1190
1221
|
zero generative cost, forever. The model is server-side and may be swapped
|
|
1191
1222
|
for a better one without any change on your side; the DSL, the output and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitida/sdk",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.5",
|
|
4
4
|
"description": "nitida — the media SDK: browser and mobile upload with resume, client-side compression, on-the-fly transforms behind a CDN, video transcode, HLS ladders and AI proxies. Multi-tenant.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|