@nitida/sdk 0.26.0 → 0.27.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/AGENTS.md +62 -0
- package/README.md +63 -2
- package/dist/index.d.ts +73 -9
- package/dist/index.js +56 -8
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +56 -8
- package/dist/server.js.map +1 -1
- package/dist/web.d.ts +2 -2
- package/dist/web.js +56 -8
- package/dist/web.js.map +1 -1
- package/package.json +2 -2
- package/skills/nitida-sdk/SKILL.md +71 -5
- package/src/audio-compat.ts +37 -0
- package/src/index.ts +51 -9
- package/src/server/index.ts +9 -0
- package/src/web/index.ts +9 -0
|
@@ -87,7 +87,7 @@ const COVER_CROP = { fit: "cover", gravity: "auto" } as const;
|
|
|
87
87
|
|
|
88
88
|
Output URL shape: `https://8ok.uk/t/format=webp,width=640/<sha16>.webp`.
|
|
89
89
|
|
|
90
|
-
⚠️ **Widths MUST be on the unsigned ladder** `TRANSFORM_WIDTHS` (`160,240,256,320,400,480,600,640,800,960,1080,1200,1280,1440,1600,1920,2560,3840`). Any other width → **HTTP 400** at the edge (DoS guard). The `TransformWidth` type makes an off-ladder width a compile error — import the type, don't hardcode magic numbers. (For a one-off custom width you'd need signed URLs; not used here.)
|
|
90
|
+
⚠️ **Widths MUST be on the unsigned ladder** `TRANSFORM_WIDTHS` (`96,128,160,240,256,320,400,480,600,640,800,960,1080,1200,1280,1440,1600,1920,2560,3840` — 20 widths). Any other width → **HTTP 400** at the edge (DoS guard). The `TransformWidth` type makes an off-ladder width a compile error — import the type, don't hardcode magic numbers. (For a one-off custom width you'd need signed URLs; not used here.)
|
|
91
91
|
|
|
92
92
|
## 2b. A responsive gallery — the widths, with their measured weight
|
|
93
93
|
|
|
@@ -221,7 +221,7 @@ export function videoUrl(sha: string, tenantId = TENANT_ID): string {
|
|
|
221
221
|
Output: `https://8ok.uk/<tenantId.toString(36)>/v/<sha16>-v.mp4`.
|
|
222
222
|
|
|
223
223
|
**Do NOT:**
|
|
224
|
-
- ❌ Use `getVideoTransformUrl` — that builds a `/t/...` transform URL, which **
|
|
224
|
+
- ❌ 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.)
|
|
225
225
|
- ❌ 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.
|
|
226
226
|
|
|
227
227
|
**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.
|
|
@@ -384,7 +384,11 @@ hls.js, which cannot start there, and fall through to the MP4. The `|| !MediaSou
|
|
|
384
384
|
covers it: native if the engine is Apple's **OR** if there is no MSE to fall back on.
|
|
385
385
|
|
|
386
386
|
**When you use hls.js, stop it guessing** — the defaults are how a fast connection still opens at
|
|
387
|
-
240p
|
|
387
|
+
240p. ⚠️ **Do NOT pass `startLevel: -1` together with `testBandwidth: true`** — measured,
|
|
388
|
+
that pair is the *cause*: on a clip short enough to be one segment the bandwidth probe IS
|
|
389
|
+
the whole video, so it plays at the bottom rung start to finish (a 5.04 s 4K asset was
|
|
390
|
+
delivered at 426×240 because of it). Leave the start level unset and raise the estimate:
|
|
391
|
+
`{ abrEwmaDefaultEstimate: 5_000_000 }`.
|
|
388
392
|
|
|
389
393
|
**The first request can answer `202`** while the background job builds the ladder (1–3 min for a
|
|
390
394
|
90 s source), then `302`s to the cached master. Keep the progressive MP4 as the fallback `<source>`
|
|
@@ -398,7 +402,7 @@ What it does NOT do is prefer Apple's engine where both work: a modern iPhone ge
|
|
|
398
402
|
hls.js tuning goes in the `config` prop:
|
|
399
403
|
|
|
400
404
|
```tsx
|
|
401
|
-
const HLS_CONFIG = { capLevelToPlayerSize: false,
|
|
405
|
+
const HLS_CONFIG = { capLevelToPlayerSize: false, abrEwmaDefaultEstimate: 5_000_000 };
|
|
402
406
|
<HlsVideo src={getHlsStreamingUrl(asset)} config={HLS_CONFIG} poster={poster} playsInline crossOrigin="anonymous" />
|
|
403
407
|
```
|
|
404
408
|
|
|
@@ -475,6 +479,68 @@ That replaces the older hand-run provisioning scripts and SQL that used to live
|
|
|
475
479
|
|
|
476
480
|
Variant preset short codes: `thumb=q, sm=s, md=m, lg=l, xl=x, original=o, poster=p, video=v`. Exts: images `webp`, video `mp4`.
|
|
477
481
|
|
|
482
|
+
|
|
483
|
+
## Private assets — `visibility`
|
|
484
|
+
|
|
485
|
+
Default is `"public"`. Set `private` and **every public door answers 404** —
|
|
486
|
+
stored variants, the raw original, the HLS ladder, and `/t/` (including the
|
|
487
|
+
poster frame of a private video). The bytes come back only through a signed URL
|
|
488
|
+
that expires.
|
|
489
|
+
|
|
490
|
+
```ts
|
|
491
|
+
import { getPrivateAssetUrl, getPrivateTransformUrl } from "@nitida/sdk";
|
|
492
|
+
// ON YOUR BACKEND, once you decided this viewer may see it:
|
|
493
|
+
await getPrivateAssetUrl(asset, "lg", signingKey, { expiresInSeconds: 300 });
|
|
494
|
+
await getPrivateTransformUrl(asset, { width: 1280 }, signingKey, { expiresInSeconds: 300 });
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
- **A 404 on a private asset is NOT a missing file.** Check `visibility` on the
|
|
498
|
+
DTO before you check storage. It is the number-one support question.
|
|
499
|
+
- **Seven URL builders throw** rather than hand you a doomed URL — `getAssetUrl`,
|
|
500
|
+
`getAssetSrcSet`, `getTransformUrl`, `getTransformSrcSet`,
|
|
501
|
+
`getVideoTransformUrl`, `getHlsStreamingUrl`, `getSignedTransformUrl` — but
|
|
502
|
+
only when the value you pass carries `visibility`. `{ sha }` alone is never
|
|
503
|
+
refused.
|
|
504
|
+
- **`exp` is mandatory**; revocation is *"within a minute"* (60 s TTL at the edge).
|
|
505
|
+
- **The signing key is a backend secret** — it mints URLs for every private
|
|
506
|
+
asset the tenant owns.
|
|
507
|
+
|
|
508
|
+
## Two ways an image gets smaller, and only one of them is yours to call
|
|
509
|
+
|
|
510
|
+
This is the question every programmatic caller gets wrong, so it is stated flat:
|
|
511
|
+
|
|
512
|
+
| | who does it | what it shrinks |
|
|
513
|
+
|---|---|---|
|
|
514
|
+
| **Client compressor** (browser / Expo) | the UI, before the PUT | the **upload**: quality 0.85, max 2880 px, WebP. iPhone 9.1 MB → 1.8 MB |
|
|
515
|
+
| **Variants + `/t/`** | the backend, on request | the **delivery**: 19 MB JPEG → 170 kB WebP at 1920 |
|
|
516
|
+
|
|
517
|
+
**The backend never recompresses the raw. Ever.** That is deliberate: the raw
|
|
518
|
+
has to stay pristine so variants are *regenerable* — the day you add AVIF or
|
|
519
|
+
raise the max dimension, the pipeline re-runs against it. A client→server lossy
|
|
520
|
+
chain bakes artifacts in forever.
|
|
521
|
+
|
|
522
|
+
So for an API/agent upload there is nothing to "turn on": you were never going
|
|
523
|
+
to compress the raw, and delivery is already optimised two ways.
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
// Ask for the rungs you will actually render…
|
|
527
|
+
await aq.upload(file, { presets: ["original", "thumb", "md", "lg"] });
|
|
528
|
+
|
|
529
|
+
// …or upload bare and let the transform route make them on demand:
|
|
530
|
+
aq.transform(asset, { width: 1280, format: "webp" }); // → /t/…, cached after the first hit
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
**`presets` defaults to `["original"]`** — a bare upload stores the raw and no
|
|
534
|
+
rendition. Since 2026-08-22 that is no longer a trap: when the DTO says a preset
|
|
535
|
+
was never materialised, `getAssetUrl` / `urlFor` **fall back to `/t/`** instead
|
|
536
|
+
of returning a URL that 404s. You still get optimised bytes; you just pay the
|
|
537
|
+
first encode. Prefer naming the presets when you know what you will render.
|
|
538
|
+
|
|
539
|
+
⚠️ `getAssetSrcSet` deliberately does **not** fall back — a srcSet promises
|
|
540
|
+
pixel widths and a transform cannot keep that promise on a source smaller than
|
|
541
|
+
the rung, because the pipeline never enlarges. An empty srcSet degrades to `src`; a lying one
|
|
542
|
+
degrades to a wrong choice.
|
|
543
|
+
|
|
478
544
|
## 7. Browser-direct uploads — three things that only fail in a real browser
|
|
479
545
|
|
|
480
546
|
Measured 2026-08-15 on the public bench at <https://media-harness.vercel.app> — no credentials
|
|
@@ -507,7 +573,7 @@ needed. Reproduce there before debugging any of these by hand.
|
|
|
507
573
|
| Symptom | Cause |
|
|
508
574
|
|---|---|
|
|
509
575
|
| **400** on an image URL | width not on `TRANSFORM_WIDTHS` ladder |
|
|
510
|
-
| **410** on a video URL |
|
|
576
|
+
| **410** on a video `/t/` URL | that video has no `poster`. With one, `/t/` returns the poster as an image, never the video — use `getAssetUrl(...,'video')` |
|
|
511
577
|
| **404** on a video URL | decimal tenant prefix (`/10/v/`) instead of base36 (`/a/v/`) — call `setTenantId` + `getAssetUrl`. Tenant 12 → `/c/v/` |
|
|
512
578
|
| `process returned no assetId` | fixed in the 2026-08-16 deploy — you are on a server deploy older than that, §7.2 |
|
|
513
579
|
| `waitReady timeout` on a video | a transcode + HLS ladder takes 1–2 min; the default `timeoutMs` is 5 min but a 4K source can beat it. Raise it, §7.2 |
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which audio uploads already play everywhere — the single source of truth for
|
|
3
|
+
* both the server's transcode guard and the client's delivery-preset choice.
|
|
4
|
+
*
|
|
5
|
+
* It lives in its own module, rather than beside the preset order that uses it,
|
|
6
|
+
* for a mechanical reason: `apps/asset-manager` imports it by relative path.
|
|
7
|
+
* The SDK is a PUBLISHED package, so its `exports` point at `dist/`, and
|
|
8
|
+
* `dist/` is gitignored — it does not exist inside the Docker image, which
|
|
9
|
+
* copies `packages/` as source. A bare `@nitida/sdk` import type-checks on any
|
|
10
|
+
* machine that built the package once and then fails the image build. (It did,
|
|
11
|
+
* on 2026-08-22, with `@nitida/asset-client`.) A single small file keeps that
|
|
12
|
+
* relative import from dragging the whole client into the server.
|
|
13
|
+
*
|
|
14
|
+
* Two copies of this list drifting apart is how a platform ends up generating
|
|
15
|
+
* a variant its own client refuses to use — which is exactly the bug this
|
|
16
|
+
* predicate was introduced to end.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `true` when a browser can play these bytes as uploaded, so re-encoding them
|
|
21
|
+
* to MP3 buys nothing.
|
|
22
|
+
*
|
|
23
|
+
* - `audio/mpeg` — unambiguous.
|
|
24
|
+
* - `audio/mp4` / `audio/aac` — plays in Safari, Chrome, Firefox and Edge on
|
|
25
|
+
* desktop and mobile. The historical worry was old AOSP builds without
|
|
26
|
+
* proprietary codecs; the call to treat AAC as universal was made with the
|
|
27
|
+
* platform's one real AAC consumer, whose viewer is WebGL — a device that
|
|
28
|
+
* cannot decode AAC cannot run that product at all, so the fallback would
|
|
29
|
+
* only ever protect a device that had already lost.
|
|
30
|
+
*
|
|
31
|
+
* Deliberately NOT here: `audio/webm` and `audio/ogg` (Opus). iOS Safari
|
|
32
|
+
* cannot decode them, and that is the case the MP3 fallback exists for.
|
|
33
|
+
*/
|
|
34
|
+
export function isUniversallyPlayableAudio(mime: string): boolean {
|
|
35
|
+
const base = (mime.split(";")[0] ?? "").trim().toLowerCase();
|
|
36
|
+
return base === "audio/mpeg" || base === "audio/mp4" || base === "audio/aac";
|
|
37
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
type VariantEntryPreset,
|
|
62
62
|
type VariantPreset,
|
|
63
63
|
} from "@nitida/asset-client";
|
|
64
|
+
import { isUniversallyPlayableAudio } from "./audio-compat";
|
|
64
65
|
|
|
65
66
|
// ---------------------------------------------------------------------------
|
|
66
67
|
// Config
|
|
@@ -114,7 +115,9 @@ export type NitidaClientOptions = {
|
|
|
114
115
|
* only when calling `aq.transform(asset, opts, { sign: true })`.
|
|
115
116
|
*
|
|
116
117
|
* 32 random bytes, generated server-side on tenant creation; fetch
|
|
117
|
-
* via `
|
|
118
|
+
* via `POST /admin/projects/:code/rotate-signing-key`, which needs a
|
|
119
|
+
* SYSTEM-scope credential the platform operator holds — your own admin key
|
|
120
|
+
* answers `403 SYSTEM_KEY_REQUIRED`. Ask for it. **Keep it
|
|
118
121
|
* server-side only** — do not ship in `NEXT_PUBLIC_*` env vars. Sign
|
|
119
122
|
* URLs from a BFF route handler, or pre-sign at build time.
|
|
120
123
|
*/
|
|
@@ -207,6 +210,7 @@ export type {
|
|
|
207
210
|
PaletteSwatch,
|
|
208
211
|
RequestablePreset,
|
|
209
212
|
ResolveSlotOptions,
|
|
213
|
+
SignAccessOptions,
|
|
210
214
|
SignedTransformOptions,
|
|
211
215
|
SlotDTO,
|
|
212
216
|
SlotResolution,
|
|
@@ -218,12 +222,16 @@ export type {
|
|
|
218
222
|
TransformWidth,
|
|
219
223
|
VariantEntryPreset,
|
|
220
224
|
VariantPreset,
|
|
225
|
+
VisibilityHint,
|
|
221
226
|
} from "@nitida/asset-client";
|
|
222
227
|
export {
|
|
228
|
+
accessMessage,
|
|
229
|
+
assertPublic,
|
|
223
230
|
bestTextContrast,
|
|
224
231
|
computeVariantDimensions,
|
|
225
232
|
configureSlotResolver,
|
|
226
233
|
contrastRatio,
|
|
234
|
+
deriveAccessKey,
|
|
227
235
|
extractAssetSha,
|
|
228
236
|
getAmbientGradient,
|
|
229
237
|
getAssetDimensions,
|
|
@@ -234,6 +242,8 @@ export {
|
|
|
234
242
|
getHlsStreamingUrl,
|
|
235
243
|
getPaletteBlurBackground,
|
|
236
244
|
getPaletteCssVars,
|
|
245
|
+
getPrivateAssetUrl,
|
|
246
|
+
getPrivateTransformUrl,
|
|
237
247
|
getSignedTransformUrl,
|
|
238
248
|
getTenantId,
|
|
239
249
|
getTextColorForBackground,
|
|
@@ -255,6 +265,7 @@ export {
|
|
|
255
265
|
serializeTransform,
|
|
256
266
|
setCdnBase,
|
|
257
267
|
setTenantId,
|
|
268
|
+
signAccessUrl,
|
|
258
269
|
signTransformUrl,
|
|
259
270
|
TRANSFORM_WIDTHS,
|
|
260
271
|
} from "@nitida/asset-client";
|
|
@@ -625,9 +636,10 @@ class AssetsApi {
|
|
|
625
636
|
}
|
|
626
637
|
|
|
627
638
|
/**
|
|
628
|
-
* Add or rebuild variants on an existing asset.
|
|
629
|
-
*
|
|
630
|
-
* the thumb variant without touching
|
|
639
|
+
* Add or rebuild variants on an existing asset. Presets are MERGED
|
|
640
|
+
* with what's there, for images AND for video — passing
|
|
641
|
+
* `{ presets: ["thumb"] }` adds the thumb variant without touching
|
|
642
|
+
* `lg`, `sm`, `original`, etc.
|
|
631
643
|
*
|
|
632
644
|
* // Day 0: upload original-only logo
|
|
633
645
|
* const { assetId } = await aq.upload(logoFile); // defaults to ["original"]
|
|
@@ -646,10 +658,18 @@ class AssetsApi {
|
|
|
646
658
|
* reading the source bytes from the permanent `original` variant —
|
|
647
659
|
* no need to re-upload.
|
|
648
660
|
*
|
|
649
|
-
* Video presets are filtered to `["poster","video","aiproxy"]`
|
|
650
|
-
* dispatched to a background job (the call returns immediately
|
|
661
|
+
* Video presets are filtered to `["poster","video","aiproxy","probe"]`
|
|
662
|
+
* and dispatched to a background job (the call returns immediately
|
|
651
663
|
* with a dispatch handle; poll `aq.assets.get(id).status` for
|
|
652
664
|
* completion).
|
|
665
|
+
*
|
|
666
|
+
* ⚠️ Before 2026-08-22 the video path REPLACED the whole variant
|
|
667
|
+
* registry instead of merging, so a partial regenerate silently
|
|
668
|
+
* deregistered `poster`, `video` and — irrecoverably — `hls`, which
|
|
669
|
+
* is not a {@link RequestablePreset} and therefore cannot be asked
|
|
670
|
+
* for again. The objects kept serving from the CDN; only the
|
|
671
|
+
* registry died. Fixed server-side; a client on an older server
|
|
672
|
+
* still loses them.
|
|
653
673
|
*/
|
|
654
674
|
async regenerate(
|
|
655
675
|
assetId: string,
|
|
@@ -1158,6 +1178,8 @@ class UsageApi {
|
|
|
1158
1178
|
}
|
|
1159
1179
|
}
|
|
1160
1180
|
|
|
1181
|
+
export { isUniversallyPlayableAudio } from "./audio-compat";
|
|
1182
|
+
|
|
1161
1183
|
export class NitidaClient {
|
|
1162
1184
|
readonly slots: SlotsApi;
|
|
1163
1185
|
readonly assets: AssetsApi;
|
|
@@ -1257,7 +1279,7 @@ export class NitidaClient {
|
|
|
1257
1279
|
if (!this.opts.signingKey) {
|
|
1258
1280
|
throw new Error(
|
|
1259
1281
|
"aq.transform({ sign: true }) requires `signingKey` in NitidaClientOptions. " +
|
|
1260
|
-
"
|
|
1282
|
+
"No signingKey on this client. The key is minted by POST /admin/projects/:code/rotate-signing-key, which needs a system-scope credential the platform operator holds — your own admin key gets 403 SYSTEM_KEY_REQUIRED, so ask for it. Then pass it to the SDK constructor on a SERVER-side instance only.",
|
|
1261
1283
|
);
|
|
1262
1284
|
}
|
|
1263
1285
|
// Signed path — custom (off-ladder) widths allowed. Empty opts → no
|
|
@@ -1633,15 +1655,35 @@ export class NitidaClient {
|
|
|
1633
1655
|
* `presets` string. Falls back through the preference order
|
|
1634
1656
|
* lg → md → sm → thumb → original (for images)
|
|
1635
1657
|
* video → poster (for videos)
|
|
1636
|
-
*
|
|
1658
|
+
* original → mp3 (for audio ALREADY playable everywhere)
|
|
1659
|
+
* mp3 → original (for any other audio)
|
|
1637
1660
|
* so an upload that was processed with e.g. `["original"]` still
|
|
1638
1661
|
* returns a non-404 URL in `aq.upload`'s result.
|
|
1662
|
+
*
|
|
1663
|
+
* ⭐ Why audio branches on the source mime (changed 2026-08-22).
|
|
1664
|
+
*
|
|
1665
|
+
* It used to be `mp3 → original` unconditionally, so `upload().cdnUrl`
|
|
1666
|
+
* handed back the server's auto-generated mp3 — libmp3lame, mono ~96 kbps —
|
|
1667
|
+
* even when the caller had uploaded an MP3 or an AAC that already plays in
|
|
1668
|
+
* every target browser. A consumer asking for "my file" silently received a
|
|
1669
|
+
* re-encoded, lower-quality one, with no error to notice.
|
|
1670
|
+
*
|
|
1671
|
+
* Measured across the platform: of 126 audio assets carrying an mp3 variant,
|
|
1672
|
+
* **105 had an `audio/mpeg` source** — an MP3 re-encoded into an MP3, for
|
|
1673
|
+
* zero compatibility gain.
|
|
1674
|
+
*
|
|
1675
|
+
* The mp3 still wins for `audio/webm`/Opus and anything exotic, which is the
|
|
1676
|
+
* case it was built for: Chrome records webm/Opus, which iOS Safari cannot
|
|
1677
|
+
* decode. That guarantee is preserved exactly; only the needless downgrade
|
|
1678
|
+
* is gone.
|
|
1639
1679
|
*/
|
|
1640
1680
|
private bestPresetForAsset(asset: AssetDTO, mime: string): VariantPreset {
|
|
1641
1681
|
const order: VariantPreset[] = mime.startsWith("video/")
|
|
1642
1682
|
? ["video", "poster"]
|
|
1643
1683
|
: mime.startsWith("audio/")
|
|
1644
|
-
?
|
|
1684
|
+
? isUniversallyPlayableAudio(mime)
|
|
1685
|
+
? ["original", "mp3"] // the upload already plays everywhere — don't hand back a re-encode
|
|
1686
|
+
: ["mp3", "original"] // exotic codec: the cross-browser mp3 earns its place
|
|
1645
1687
|
: ["lg", "md", "sm", "thumb", "xl", "original"];
|
|
1646
1688
|
return (
|
|
1647
1689
|
order.find((p) => hasPreset(asset, p)) ?? this.defaultPresetForMime(mime)
|
package/src/server/index.ts
CHANGED
|
@@ -94,6 +94,8 @@ export {
|
|
|
94
94
|
type AssetDTO,
|
|
95
95
|
type AssetPalette,
|
|
96
96
|
type AssetVariant,
|
|
97
|
+
accessMessage,
|
|
98
|
+
assertPublic,
|
|
97
99
|
bestTextContrast,
|
|
98
100
|
type ComposeMarketingComposition,
|
|
99
101
|
type ComposeMarketingOptions,
|
|
@@ -103,6 +105,7 @@ export {
|
|
|
103
105
|
computeVariantDimensions,
|
|
104
106
|
configureSlotResolver,
|
|
105
107
|
contrastRatio,
|
|
108
|
+
deriveAccessKey,
|
|
106
109
|
extractAssetSha,
|
|
107
110
|
getAmbientGradient,
|
|
108
111
|
getAssetDimensions,
|
|
@@ -113,6 +116,8 @@ export {
|
|
|
113
116
|
getHlsStreamingUrl,
|
|
114
117
|
getPaletteBlurBackground,
|
|
115
118
|
getPaletteCssVars,
|
|
119
|
+
getPrivateAssetUrl,
|
|
120
|
+
getPrivateTransformUrl,
|
|
116
121
|
getSignedTransformUrl,
|
|
117
122
|
getTenantId,
|
|
118
123
|
getTextColorForBackground,
|
|
@@ -123,6 +128,7 @@ export {
|
|
|
123
128
|
hasPreset,
|
|
124
129
|
hlsLadderAlignment,
|
|
125
130
|
invalidateSlotCache,
|
|
131
|
+
isUniversallyPlayableAudio,
|
|
126
132
|
iteratePaletteSwatches,
|
|
127
133
|
mimeFromFileName,
|
|
128
134
|
type NitidaClientOptions,
|
|
@@ -139,6 +145,7 @@ export {
|
|
|
139
145
|
relativeLuminance,
|
|
140
146
|
resolveSlot,
|
|
141
147
|
resolveSlots,
|
|
148
|
+
type SignAccessOptions,
|
|
142
149
|
type SignedTransformOptions,
|
|
143
150
|
type SlotDTO,
|
|
144
151
|
type SlotHistoryEntry,
|
|
@@ -146,6 +153,7 @@ export {
|
|
|
146
153
|
serializeTransform,
|
|
147
154
|
setCdnBase,
|
|
148
155
|
setTenantId,
|
|
156
|
+
signAccessUrl,
|
|
149
157
|
signTransformUrl,
|
|
150
158
|
TRANSFORM_WIDTHS,
|
|
151
159
|
type TransformEffect,
|
|
@@ -164,4 +172,5 @@ export {
|
|
|
164
172
|
type UsageWindow,
|
|
165
173
|
type VariantEntryPreset,
|
|
166
174
|
type VariantPreset,
|
|
175
|
+
type VisibilityHint,
|
|
167
176
|
} from "..";
|
package/src/web/index.ts
CHANGED
|
@@ -111,6 +111,8 @@ export {
|
|
|
111
111
|
type AssetDTO,
|
|
112
112
|
type AssetPalette,
|
|
113
113
|
type AssetVariant,
|
|
114
|
+
accessMessage,
|
|
115
|
+
assertPublic,
|
|
114
116
|
bestTextContrast,
|
|
115
117
|
type ComposeMarketingComposition,
|
|
116
118
|
type ComposeMarketingOptions,
|
|
@@ -120,6 +122,7 @@ export {
|
|
|
120
122
|
computeVariantDimensions,
|
|
121
123
|
configureSlotResolver,
|
|
122
124
|
contrastRatio,
|
|
125
|
+
deriveAccessKey,
|
|
123
126
|
extractAssetSha,
|
|
124
127
|
getAmbientGradient,
|
|
125
128
|
getAssetDimensions,
|
|
@@ -130,6 +133,8 @@ export {
|
|
|
130
133
|
getHlsStreamingUrl,
|
|
131
134
|
getPaletteBlurBackground,
|
|
132
135
|
getPaletteCssVars,
|
|
136
|
+
getPrivateAssetUrl,
|
|
137
|
+
getPrivateTransformUrl,
|
|
133
138
|
getSignedTransformUrl,
|
|
134
139
|
getTenantId,
|
|
135
140
|
getTextColorForBackground,
|
|
@@ -140,6 +145,7 @@ export {
|
|
|
140
145
|
hasPreset,
|
|
141
146
|
hlsLadderAlignment,
|
|
142
147
|
invalidateSlotCache,
|
|
148
|
+
isUniversallyPlayableAudio,
|
|
143
149
|
iteratePaletteSwatches,
|
|
144
150
|
mimeFromFileName,
|
|
145
151
|
type PaletteSwatch,
|
|
@@ -155,6 +161,7 @@ export {
|
|
|
155
161
|
relativeLuminance,
|
|
156
162
|
resolveSlot,
|
|
157
163
|
resolveSlots,
|
|
164
|
+
type SignAccessOptions,
|
|
158
165
|
type SignedTransformOptions,
|
|
159
166
|
type SlotDTO,
|
|
160
167
|
type SlotHistoryEntry,
|
|
@@ -162,6 +169,7 @@ export {
|
|
|
162
169
|
serializeTransform,
|
|
163
170
|
setCdnBase,
|
|
164
171
|
setTenantId,
|
|
172
|
+
signAccessUrl,
|
|
165
173
|
signTransformUrl,
|
|
166
174
|
TRANSFORM_WIDTHS,
|
|
167
175
|
type TransformEffect,
|
|
@@ -180,6 +188,7 @@ export {
|
|
|
180
188
|
type UsageWindow,
|
|
181
189
|
type VariantEntryPreset,
|
|
182
190
|
type VariantPreset,
|
|
191
|
+
type VisibilityHint,
|
|
183
192
|
} from "..";
|
|
184
193
|
|
|
185
194
|
// Multipart uploader helpers are NOT re-exported from this subpath.
|