@nitida/sdk 0.24.0 → 0.25.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 +10 -9
- package/README.md +161 -154
- package/dist/index.d.ts +79 -50
- package/dist/index.js +73 -28
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +9 -7
- package/dist/server.js +51 -28
- package/dist/server.js.map +1 -1
- package/dist/web.d.ts +11 -12
- package/dist/web.js +51 -28
- package/dist/web.js.map +1 -1
- package/package.json +2 -2
- package/skills/nitida-sdk/SKILL.md +215 -91
- package/src/index.ts +114 -51
- package/src/server/index.ts +9 -7
- package/src/web/index.ts +16 -17
package/dist/web.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { AssetDTO, AssetVariant, ResolveSlotOptions, SignedTransformOptions, Slo
|
|
|
17
17
|
* // Point at your BFF route — the SDK calls
|
|
18
18
|
* // `${endpoint}/assets/by-hash/...`, `${endpoint}/slots/...`, etc.
|
|
19
19
|
* endpoint: "/api/am", // relative ⇒ same-origin proxy
|
|
20
|
-
* tenantCode: "
|
|
20
|
+
* tenantCode: "acme-co",
|
|
21
21
|
* tenantId: 1,
|
|
22
22
|
* // NO apiKey — the type strips it. Your BFF injects the bearer.
|
|
23
23
|
* });
|
|
@@ -32,7 +32,7 @@ export { AssetDTO, AssetVariant, ResolveSlotOptions, SignedTransformOptions, Slo
|
|
|
32
32
|
* return fetch(url, {
|
|
33
33
|
* headers: {
|
|
34
34
|
* Authorization: `Bearer ${process.env.AQUIENPZ_API_KEY!}`,
|
|
35
|
-
* "X-Tenant-Code": "
|
|
35
|
+
* "X-Tenant-Code": "acme-co",
|
|
36
36
|
* },
|
|
37
37
|
* });
|
|
38
38
|
* }
|
|
@@ -66,7 +66,7 @@ export { AssetDTO, AssetVariant, ResolveSlotOptions, SignedTransformOptions, Slo
|
|
|
66
66
|
*
|
|
67
67
|
* const aq = new NitidaClient({
|
|
68
68
|
* endpoint: "/api/am", // OK: relative → same-origin BFF
|
|
69
|
-
* tenantCode: "
|
|
69
|
+
* tenantCode: "acme-co",
|
|
70
70
|
* tenantId: 1,
|
|
71
71
|
* // apiKey: "amk_rt_...", // ERROR: TS error: not assignable
|
|
72
72
|
* });
|
|
@@ -87,17 +87,16 @@ declare class NitidaClient extends NitidaClient$1 {
|
|
|
87
87
|
type CompressStage = "convertingHeic" | "compressing" | "compressingKeepingDimensions";
|
|
88
88
|
/**
|
|
89
89
|
* Subset of compressorjs options exposed by the SDK. Matches the
|
|
90
|
-
*
|
|
91
|
-
* production back-office uploader.
|
|
90
|
+
* `DEFAULT_COMPRESSION_OPTIONS` shape below.
|
|
92
91
|
*/
|
|
93
92
|
type CompressOptions = {
|
|
94
|
-
/** 0..1. Default 0.80
|
|
93
|
+
/** 0..1. Default 0.80. */
|
|
95
94
|
quality?: number;
|
|
96
|
-
/** Output format. Default `"image/webp"
|
|
95
|
+
/** Output format. Default `"image/webp"`. */
|
|
97
96
|
mimeType?: "image/jpeg" | "image/webp";
|
|
98
|
-
/** Max edge in pixels. Default 3840
|
|
97
|
+
/** Max edge in pixels. Default 3840. */
|
|
99
98
|
maxWidth?: number;
|
|
100
|
-
/** Default 3840
|
|
99
|
+
/** Max edge in pixels. Default 3840. */
|
|
101
100
|
maxHeight?: number;
|
|
102
101
|
/**
|
|
103
102
|
* compressorjs `convertSize`: PNG > this byte count auto-converts to
|
|
@@ -117,9 +116,9 @@ type CompressOptions = {
|
|
|
117
116
|
onProgress?: (stage: CompressStage) => void;
|
|
118
117
|
};
|
|
119
118
|
/**
|
|
120
|
-
*
|
|
121
|
-
* from `@nitida/asset-compressor-web`'s
|
|
122
|
-
* SDK overrides at call time.
|
|
119
|
+
* Defaults tuned against a production photo-upload workload. These
|
|
120
|
+
* intentionally differ from `@nitida/asset-compressor-web`'s
|
|
121
|
+
* package-level defaults — the SDK overrides at call time.
|
|
123
122
|
*/
|
|
124
123
|
declare const DEFAULT_COMPRESSION_OPTIONS: Required<Omit<CompressOptions, "keepOriginalDimensions" | "convertHeic" | "onProgress">>;
|
|
125
124
|
type CompressResult = {
|
package/dist/web.js
CHANGED
|
@@ -16,21 +16,43 @@ import {
|
|
|
16
16
|
setTenantId
|
|
17
17
|
} from "@nitida/asset-client";
|
|
18
18
|
import {
|
|
19
|
+
bestTextContrast,
|
|
19
20
|
computeVariantDimensions,
|
|
21
|
+
configureSlotResolver as configureSlotResolver2,
|
|
22
|
+
contrastRatio,
|
|
20
23
|
extractAssetSha,
|
|
24
|
+
getAmbientGradient,
|
|
21
25
|
getAssetDimensions,
|
|
22
26
|
getAssetSrcSet as getAssetSrcSet2,
|
|
23
27
|
getAssetUrl as getAssetUrl2,
|
|
28
|
+
getCdnBase,
|
|
29
|
+
getHlsLadder,
|
|
24
30
|
getHlsStreamingUrl as getHlsStreamingUrl2,
|
|
31
|
+
getPaletteBlurBackground,
|
|
32
|
+
getPaletteCssVars,
|
|
25
33
|
getSignedTransformUrl as getSignedTransformUrl2,
|
|
26
34
|
getTenantId,
|
|
35
|
+
getTextColorForBackground,
|
|
27
36
|
getTransformSrcSet as getTransformSrcSet2,
|
|
28
37
|
getTransformUrl as getTransformUrl2,
|
|
29
38
|
getVideoTransformUrl as getVideoTransformUrl2,
|
|
30
39
|
hasPreset as hasPreset2,
|
|
40
|
+
hlsLadderAlignment,
|
|
41
|
+
invalidateSlotCache as invalidateSlotCache2,
|
|
42
|
+
iteratePaletteSwatches,
|
|
43
|
+
PRESET_EXT,
|
|
44
|
+
PRESET_LONG,
|
|
45
|
+
PRESET_MAX_DIM,
|
|
46
|
+
PRESET_SHORT,
|
|
47
|
+
pickAmbientBackground,
|
|
48
|
+
relativeLuminance,
|
|
49
|
+
resolveSlot as resolveSlot2,
|
|
50
|
+
resolveSlots as resolveSlots2,
|
|
31
51
|
serializeTransform,
|
|
52
|
+
setCdnBase as setCdnBase2,
|
|
32
53
|
setTenantId as setTenantId2,
|
|
33
|
-
signTransformUrl
|
|
54
|
+
signTransformUrl,
|
|
55
|
+
TRANSFORM_WIDTHS
|
|
34
56
|
} from "@nitida/asset-client";
|
|
35
57
|
function endpointUrl(opts, path, searchParams) {
|
|
36
58
|
const endpoint = opts.endpoint.replace(/\/+$/, "");
|
|
@@ -223,8 +245,8 @@ var AssetsApi = class {
|
|
|
223
245
|
* const v = await aq.assets.variants(logoId);
|
|
224
246
|
* v.map((x) => x.preset); // → ("thumb" | "sm" | … | "original")[]
|
|
225
247
|
*
|
|
226
|
-
* ⚠️ Returns `[]` — not an error — against
|
|
227
|
-
* 2026-08-17
|
|
248
|
+
* ⚠️ Returns `[]` — not an error — against a server older than the
|
|
249
|
+
* 2026-08-17 release, which never sent the field at all. An empty
|
|
228
250
|
* array is therefore "no variants OR old server". For a plain existence
|
|
229
251
|
* check prefer `hasPreset(dto, preset)` on `dto.presets`, which every server
|
|
230
252
|
* version sends; use this when you need the URLs and sizes.
|
|
@@ -250,12 +272,13 @@ var AssetsApi = class {
|
|
|
250
272
|
* Passing no presets re-runs the FULL default pipeline for that
|
|
251
273
|
* asset's kind (thumb+sm+md+lg for images, poster+video for video).
|
|
252
274
|
*
|
|
253
|
-
* If the asset was uploaded original-only and the
|
|
254
|
-
* already
|
|
255
|
-
* bytes from
|
|
275
|
+
* If the asset was uploaded original-only and the ~24 h grace window
|
|
276
|
+
* on the uploaded bytes has already closed, the route falls back to
|
|
277
|
+
* reading the source bytes from the permanent `original` variant —
|
|
278
|
+
* no need to re-upload.
|
|
256
279
|
*
|
|
257
280
|
* Video presets are filtered to `["poster","video","aiproxy"]` and
|
|
258
|
-
* dispatched to
|
|
281
|
+
* dispatched to a background job (the call returns immediately
|
|
259
282
|
* with a dispatch handle; poll `aq.assets.get(id).status` for
|
|
260
283
|
* completion).
|
|
261
284
|
*/
|
|
@@ -283,13 +306,13 @@ var AssetsApi = class {
|
|
|
283
306
|
return await r.json();
|
|
284
307
|
}
|
|
285
308
|
/**
|
|
286
|
-
* Request a presigned
|
|
309
|
+
* Request a presigned storage PUT URL for direct browser-side uploads.
|
|
287
310
|
*
|
|
288
311
|
* Mirrors the first half of `aq.upload()` — the caller (typically a
|
|
289
312
|
* BFF / share-link dropzone) computes sha256 in the browser, then
|
|
290
|
-
* uploads bytes straight to
|
|
291
|
-
* POSTs `process.body` to `/assets/process` (see {@link processAndWait})
|
|
292
|
-
* once
|
|
313
|
+
* uploads bytes straight to object storage with the returned `upload.url`,
|
|
314
|
+
* then POSTs `process.body` to `/assets/process` (see {@link processAndWait})
|
|
315
|
+
* once storage has the bytes.
|
|
293
316
|
*
|
|
294
317
|
* If the sha is already known to the tenant the server short-circuits
|
|
295
318
|
* with `{ deduped: true, asset }` — no PUT needed.
|
|
@@ -301,16 +324,16 @@ var AssetsApi = class {
|
|
|
301
324
|
* if (presign.deduped) return presign.asset; // those bytes already exist; none fly
|
|
302
325
|
*
|
|
303
326
|
* // BROWSER: PUT straight to presign.upload.url — the bytes never touch your server.
|
|
304
|
-
* // ⚠️
|
|
305
|
-
* // Symptom when it is not: "PUT failed: network error" with every earlier step
|
|
306
|
-
* // and it cannot be fixed in this SDK, in your app, or
|
|
327
|
+
* // ⚠️ The STORAGE BUCKET answers that preflight itself, so your origin must be in its CORS
|
|
328
|
+
* // policy. Symptom when it is not: "PUT failed: network error" with every earlier step
|
|
329
|
+
* // green — and it cannot be fixed in this SDK, in your app, or by the API's allowed origins.
|
|
307
330
|
*
|
|
308
331
|
* // SERVER again, forwarding presign.process.body VERBATIM:
|
|
309
332
|
* const asset = await aq.assets.processAndWait(presign.process.body, { timeoutMs: 300_000 });
|
|
310
333
|
* ```
|
|
311
334
|
*
|
|
312
335
|
* Works for images AND video. A video answers immediately with
|
|
313
|
-
* `{ assetId, status: "processing" }` while a
|
|
336
|
+
* `{ assetId, status: "processing" }` while a background job transcodes, so
|
|
314
337
|
* give `processAndWait` a bigger `timeoutMs` (a transcode + HLS ladder runs
|
|
315
338
|
* 1–2 min; 300_000 is a sane floor).
|
|
316
339
|
*/
|
|
@@ -338,7 +361,7 @@ var AssetsApi = class {
|
|
|
338
361
|
* {@link presignUploadUrl} call, then poll until the asset transitions
|
|
339
362
|
* to `ready` or `failed`. Throws on `failed` or timeout.
|
|
340
363
|
*
|
|
341
|
-
* Use this when bytes were uploaded directly from the browser to
|
|
364
|
+
* Use this when bytes were uploaded directly from the browser to storage —
|
|
342
365
|
* `aq.upload()` already does presign + PUT + process + wait in one
|
|
343
366
|
* step when the server holds the bytes.
|
|
344
367
|
*/
|
|
@@ -387,7 +410,7 @@ var AssetsApi = class {
|
|
|
387
410
|
* {@link waitReady} (typical timeout: 10 min for multi-segment kits).
|
|
388
411
|
*
|
|
389
412
|
* Tenant scope is inherited from the SDK client; `tenantCode` is added
|
|
390
|
-
* to the request body so the
|
|
413
|
+
* to the request body so the background job can resolve it without
|
|
391
414
|
* re-reading the header.
|
|
392
415
|
*/
|
|
393
416
|
async composeMarketing(opts) {
|
|
@@ -553,12 +576,12 @@ var NitidaClient = class {
|
|
|
553
576
|
* Build an on-the-fly VIDEO transform URL — Phase 4.
|
|
554
577
|
*
|
|
555
578
|
* Same DSL shape as `transform()` but the URL has a `.mp4` (default)
|
|
556
|
-
* or `.webm` extension and the server routes the request to a
|
|
557
|
-
*
|
|
579
|
+
* or `.webm` extension and the server routes the request to a
|
|
580
|
+
* background job for video encoding (vs the inline pipeline for
|
|
558
581
|
* images).
|
|
559
582
|
*
|
|
560
583
|
* On the first request the route returns **202 Accepted** with
|
|
561
|
-
* `Retry-After: 10` while the
|
|
584
|
+
* `Retry-After: 10` while the encode runs (typically 5-30 s for a
|
|
562
585
|
* short clip). The response body includes `outputUrl` which is the
|
|
563
586
|
* eventual CDN URL — poll the same transform URL after the
|
|
564
587
|
* retry-after window to get a 302 redirect to it.
|
|
@@ -596,7 +619,7 @@ var NitidaClient = class {
|
|
|
596
619
|
* />
|
|
597
620
|
*
|
|
598
621
|
* On the first request the server returns **202 Accepted** while a
|
|
599
|
-
*
|
|
622
|
+
* background job builds the multi-rung ladder (typically 1-3 min for
|
|
600
623
|
* a 90 s source — five rungs of 240p/360p/480p/720p/1080p @ AAC).
|
|
601
624
|
* Subsequent requests hit the cache → **302** to the master.m3u8.
|
|
602
625
|
*
|
|
@@ -617,13 +640,13 @@ var NitidaClient = class {
|
|
|
617
640
|
* but isn't always available depending on the runtime).
|
|
618
641
|
*/
|
|
619
642
|
/**
|
|
620
|
-
* Upload bytes end to end: optional client compression → sha256 → presign → **direct-to-
|
|
643
|
+
* Upload bytes end to end: optional client compression → sha256 → presign → **direct-to-storage PUT**
|
|
621
644
|
* → `/assets/process` → wait until the asset is ready.
|
|
622
645
|
*
|
|
623
646
|
* ⚠️ `presets` decides what exists FOREVER. Omit it and only `original` is written; ask for
|
|
624
647
|
* `["thumb"]` and the bytes you just uploaded are **not retrievable**. A variant not requested in
|
|
625
|
-
* this first ingest cannot be added later once the
|
|
626
|
-
* "97 files archived successfully, zero recoverable".
|
|
648
|
+
* this first ingest cannot be added later once the ~24 h grace window on the uploaded bytes
|
|
649
|
+
* closes — measured once as "97 files archived successfully, zero recoverable".
|
|
627
650
|
*
|
|
628
651
|
* @example Deliver an image on a site (the responsive ladder)
|
|
629
652
|
* ```ts
|
|
@@ -654,11 +677,11 @@ var NitidaClient = class {
|
|
|
654
677
|
* @example Video — and what does NOT work there
|
|
655
678
|
* ```ts
|
|
656
679
|
* // `original` is accepted and then silently DROPPED: /assets/process filters video presets to
|
|
657
|
-
* // {poster, video, aiproxy, probe} before dispatching the transcode
|
|
680
|
+
* // {poster, video, aiproxy, probe} before dispatching the background transcode.
|
|
658
681
|
* await aq.upload(clip, { fileName: "tour.mp4", presets: ["poster", "video"] });
|
|
659
682
|
*
|
|
660
|
-
* // Omit `aiproxy`/`probe` unless the asset really goes to a vision model — they cost
|
|
661
|
-
* // and permanent
|
|
683
|
+
* // Omit `aiproxy`/`probe` unless the asset really goes to a vision model — they cost encode
|
|
684
|
+
* // time and permanent stored objects that nothing else reads.
|
|
662
685
|
* ```
|
|
663
686
|
*/
|
|
664
687
|
async upload(input, opts = {}) {
|
|
@@ -731,7 +754,7 @@ var NitidaClient = class {
|
|
|
731
754
|
body: new Blob([bytes], { type: mime })
|
|
732
755
|
});
|
|
733
756
|
if (!putR.ok)
|
|
734
|
-
throw new Error(`
|
|
757
|
+
throw new Error(`Storage PUT ${putR.status}: ${await putR.text()}`);
|
|
735
758
|
const procR = await fetch(endpointHref(this.opts, presign.process.url), {
|
|
736
759
|
method: "POST",
|
|
737
760
|
headers: {
|