@nitida/sdk 0.30.1 → 0.31.0
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 +25 -6
- package/package.json +2 -2
- package/skills/nitida-sdk/SKILL.md +11 -2
package/README.md
CHANGED
|
@@ -661,7 +661,13 @@ with `aq.assets.regenerate()` (no re-upload required).
|
|
|
661
661
|
// Default: only the original variant lands on the CDN.
|
|
662
662
|
const { assetId, cdnUrl } = await aq.upload(logoFile);
|
|
663
663
|
// asset.presets === "o"
|
|
664
|
-
// cdnUrl = https://8ok.uk/<sha>-o.svg
|
|
664
|
+
// cdnUrl = https://8ok.uk/<tid b36>/v/<sha>-o.svg ← the tenant segment is not optional
|
|
665
|
+
|
|
666
|
+
// Processing is asynchronous. `upload()` returns as soon as the bytes are
|
|
667
|
+
// accepted; the variants are not on the CDN yet. Wait for them:
|
|
668
|
+
const ready = await aq.assets.waitReady(assetId, 90_000); // MILLISECONDS
|
|
669
|
+
// ready.presets is the compact string ("o", "lmoqs", …), ALPHABETICALLY
|
|
670
|
+
// sorted — not in the order you asked for.
|
|
665
671
|
```
|
|
666
672
|
|
|
667
673
|
**Responsive ladder (the old default — now explicit):**
|
|
@@ -1307,12 +1313,25 @@ server-side pipeline (a platform-wide addition, not a per-tenant one).
|
|
|
1307
1313
|
|
|
1308
1314
|
### CDN URL format
|
|
1309
1315
|
|
|
1310
|
-
`<cdnBase>/<sha16>-<presetCode>.<ext>`
|
|
1316
|
+
`<cdnBase>/<tenantId base36>/v/<sha16>-<presetCode>.<ext>`
|
|
1317
|
+
|
|
1318
|
+
Example: `https://8ok.uk/f/v/c482458e824c730e-q.webp` — the `thumb` preset of
|
|
1319
|
+
sha `c482458e…` as WebP, for **tenant 15** (`15` in base36 is `f`).
|
|
1320
|
+
|
|
1321
|
+
⚠️ **The tenant segment is not optional, and it is base36.** `/15/…` 404s;
|
|
1322
|
+
so does a bare `/<sha16>-q.webp` with no tenant at all. Nothing serves that
|
|
1323
|
+
shape — it is not a legacy path, it is a 404. Call `setTenantId(id)` once at
|
|
1324
|
+
boot (or construct a `NitidaClient` with `tenantId`, which does it for you);
|
|
1325
|
+
without it the builders **throw** rather than hand you a URL that cannot work.
|
|
1326
|
+
|
|
1327
|
+
Within one tenant the path is content-addressed: the same source bytes always
|
|
1328
|
+
produce the same URL, and that URL never invalidates.
|
|
1311
1329
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1330
|
+
> Before `@nitida/asset-client@0.20.0` this section documented the bare
|
|
1331
|
+
> `<cdnBase>/<sha16>-<preset>.<ext>` form, with an example that 404s, and said
|
|
1332
|
+
> the URL was the same "regardless of which tenant uploaded them". That stopped
|
|
1333
|
+
> being true at the tenant-prefix cutover. If you copied a URL from an older
|
|
1334
|
+
> README, add the `<tid b36>/v/` segment.
|
|
1316
1335
|
|
|
1317
1336
|
## Auth
|
|
1318
1337
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitida/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
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": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"react": ">=18",
|
|
76
|
-
"@nitida/asset-client": "^0.
|
|
76
|
+
"@nitida/asset-client": "^0.20.0",
|
|
77
77
|
"@nitida/asset-compressor-web": "^0.6.1",
|
|
78
78
|
"@nitida/asset-compressor-native": "^0.2.1"
|
|
79
79
|
},
|
|
@@ -60,7 +60,7 @@ import { setCdnBase, setTenantId } from "@nitida/asset-client";
|
|
|
60
60
|
const TENANT_ID = Number(process.env.NEXT_PUBLIC_NITIDA_TENANT_ID) || /* your id */ 0;
|
|
61
61
|
|
|
62
62
|
setCdnBase("https://8ok.uk"); // OPTIONAL — this is already the default; set it only if you were given another host
|
|
63
|
-
setTenantId(TENANT_ID); // REQUIRED for
|
|
63
|
+
setTenantId(TENANT_ID); // REQUIRED for EVERY variant URL — images too (base36 prefix), see §3
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
`NEXT_PUBLIC_*` so the tenant id reaches the client bundle (hero/about videos render client-side). The runtime read-only consumer needs only these public vars — the `amk_rt_*` runtime key is for **uploads** (server-only), not for building URLs.
|
|
@@ -159,6 +159,10 @@ everyone, and the ladder buys you nothing.
|
|
|
159
159
|
that your sources can sustain.
|
|
160
160
|
(There IS a paid, separate `POST /assets/:id/upscale` that genuinely enlarges
|
|
161
161
|
with a model. It is not the transform route and it is not free — §8g.)
|
|
162
|
+
- ⚠️ **There is no upscale — the master is the ceiling.** Measured: a 2400 px
|
|
163
|
+
master asked for `width=2560` returns **2400 px**. Put widths in the `srcSet`
|
|
164
|
+
that your sources can sustain — asking for more is not an error, it is a
|
|
165
|
+
smaller image than you think you requested.
|
|
162
166
|
- ⚠️ The **first** request of each width is generated cold, then cached at the
|
|
163
167
|
edge immutably. Warm them after upload if the first visitor matters.
|
|
164
168
|
|
|
@@ -223,6 +227,11 @@ Output: `https://8ok.uk/<tenantId.toString(36)>/v/<sha16>-v.mp4`.
|
|
|
223
227
|
|
|
224
228
|
**Do NOT:**
|
|
225
229
|
- ❌ Use `getVideoTransformUrl` — that builds a `/t/...` transform URL, which never returns playable video. On a video sha `/t/` transforms the **poster frame**: `200 image/webp` with `x-transform-source: poster` when a poster exists, `410` when it does not. (`getVideoTransformUrl` is for on-the-fly re-encodes, a different feature.)
|
|
230
|
+
- ❌ Use `getVideoTransformUrl` for the HLS entry — that builds a `/t/…`
|
|
231
|
+
transform URL. ⚠️ **A 410 there means the SOURCE BYTES ARE GONE**
|
|
232
|
+
(`source_unavailable`), **not** that you used the wrong builder. Do not go
|
|
233
|
+
change the call site while data loss goes unnoticed. (`getVideoTransformUrl`
|
|
234
|
+
is for on-the-fly re-encodes — a different feature.)
|
|
226
235
|
- ❌ Hand-roll the path with the decimal tenant id. The path segment is **base36**: `tenantId.toString(36)`. **Tenant 10 → `/a/v/`**, and the decimal `/10/v/` **404s**. This is invisible for tenants ≤ 9 (`8`→`8`, `9`→`9`) and bit a real migration only at tenant 10. Always delegate to `getAssetUrl` so the encoding can't drift.
|
|
227
236
|
|
|
228
237
|
**Audio IS supported (updated 2026-07-01 — verify against the SDK types, this used to say "not supported").** The platform recognizes `kind: "image" | "video" | "document" | "audio" | "other"` and ships an **`mp3`** variant preset (`VariantPreset` in `@nitida/asset-client`). Uploads are hash-deduped (byte-identical re-uploads return the existing sha — that's *byte* dedup, NOT semantic "find a similar track"). `nt.upload` also accepts an `audioTrack` on video-composition calls. Serve via the `mp3` preset / `original`. Confirm the current preset/kind list in `node_modules/@nitida/asset-client/dist/index.d.ts` before relying on a specific ext.
|
|
@@ -508,7 +517,7 @@ That replaces the older hand-run provisioning scripts and SQL that used to live
|
|
|
508
517
|
| Poster | `getAssetUrl({sha}, 'poster')` | `/<tid b36>/v/<sha>-p.webp` |
|
|
509
518
|
| Sha from URL | `extractAssetSha(url)` | — |
|
|
510
519
|
|
|
511
|
-
Variant preset short codes
|
|
520
|
+
Variant preset short codes — **all of them**: `thumb=q, sm=s, md=m, lg=l, xl=x, original=o, poster=p, video=v, aiproxy=a, hls=h, mp3=mp3`. ⚠️ `mp3` is the one irregular case: three characters, not one. Exts: images `webp`, video `mp4`.
|
|
512
521
|
|
|
513
522
|
|
|
514
523
|
## Private assets — `visibility`
|