@nitida/sdk 0.26.0 → 0.27.1

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/dist/web.js CHANGED
@@ -15,11 +15,23 @@ import {
15
15
  setCdnBase,
16
16
  setTenantId
17
17
  } from "@nitida/asset-client";
18
+
19
+ // src/audio-compat.ts
20
+ function isUniversallyPlayableAudio(mime) {
21
+ const base = (mime.split(";")[0] ?? "").trim().toLowerCase();
22
+ return base === "audio/mpeg" || base === "audio/mp4" || base === "audio/aac";
23
+ }
24
+
25
+ // src/index.ts
18
26
  import {
27
+ accessMessage,
28
+ assertPublic,
29
+ assertSha,
19
30
  bestTextContrast,
20
31
  computeVariantDimensions,
21
32
  configureSlotResolver as configureSlotResolver2,
22
33
  contrastRatio,
34
+ deriveAccessKey,
23
35
  extractAssetSha,
24
36
  getAmbientGradient,
25
37
  getAssetDimensions,
@@ -30,6 +42,8 @@ import {
30
42
  getHlsStreamingUrl as getHlsStreamingUrl2,
31
43
  getPaletteBlurBackground,
32
44
  getPaletteCssVars,
45
+ getPrivateAssetUrl,
46
+ getPrivateTransformUrl,
33
47
  getSignedTransformUrl as getSignedTransformUrl2,
34
48
  getTenantId,
35
49
  getTextColorForBackground,
@@ -51,6 +65,7 @@ import {
51
65
  serializeTransform,
52
66
  setCdnBase as setCdnBase2,
53
67
  setTenantId as setTenantId2,
68
+ signAccessUrl,
54
69
  signTransformUrl,
55
70
  TRANSFORM_WIDTHS
56
71
  } from "@nitida/asset-client";
@@ -256,9 +271,10 @@ var AssetsApi = class {
256
271
  return Array.isArray(dto.variants) ? dto.variants : [];
257
272
  }
258
273
  /**
259
- * Add or rebuild variants on an existing asset. Image presets are
260
- * MERGED with what's there passing `{ presets: ["thumb"] }` adds
261
- * the thumb variant without touching `lg`, `sm`, `original`, etc.
274
+ * Add or rebuild variants on an existing asset. Presets are MERGED
275
+ * with what's there, for images AND for video passing
276
+ * `{ presets: ["thumb"] }` adds the thumb variant without touching
277
+ * `lg`, `sm`, `original`, etc.
262
278
  *
263
279
  * // Day 0: upload original-only logo
264
280
  * const { assetId } = await aq.upload(logoFile); // defaults to ["original"]
@@ -277,10 +293,18 @@ var AssetsApi = class {
277
293
  * reading the source bytes from the permanent `original` variant —
278
294
  * no need to re-upload.
279
295
  *
280
- * Video presets are filtered to `["poster","video","aiproxy"]` and
281
- * dispatched to a background job (the call returns immediately
296
+ * Video presets are filtered to `["poster","video","aiproxy","probe"]`
297
+ * and dispatched to a background job (the call returns immediately
282
298
  * with a dispatch handle; poll `aq.assets.get(id).status` for
283
299
  * completion).
300
+ *
301
+ * ⚠️ Before 2026-08-22 the video path REPLACED the whole variant
302
+ * registry instead of merging, so a partial regenerate silently
303
+ * deregistered `poster`, `video` and — irrecoverably — `hls`, which
304
+ * is not a {@link RequestablePreset} and therefore cannot be asked
305
+ * for again. The objects kept serving from the CDN; only the
306
+ * registry died. Fixed server-side; a client on an older server
307
+ * still loses them.
284
308
  */
285
309
  async regenerate(assetId, opts = {}) {
286
310
  const r = await fetch(
@@ -548,7 +572,7 @@ var NitidaClient = class {
548
572
  }
549
573
  if (!this.opts.signingKey) {
550
574
  throw new Error(
551
- "aq.transform({ sign: true }) requires `signingKey` in NitidaClientOptions. Pull the tenant's signing key from /admin/tenants/:id and pass it to the SDK constructor on a SERVER-side instance only."
575
+ "aq.transform({ sign: true }) requires `signingKey` in NitidaClientOptions. 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 \u2014 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."
552
576
  );
553
577
  }
554
578
  return getSignedTransformUrl(asset, opts, this.opts.signingKey) ?? Promise.resolve(this.urlFor(asset, "lg"));
@@ -729,6 +753,7 @@ var NitidaClient = class {
729
753
  return {
730
754
  assetId: existing.id,
731
755
  sha256: sha,
756
+ sha: sha.slice(0, 16),
732
757
  cdnUrl: this.urlFor(existing, this.bestPresetForAsset(existing, mime))
733
758
  };
734
759
  }
@@ -745,6 +770,7 @@ var NitidaClient = class {
745
770
  return {
746
771
  assetId: presign.asset.id,
747
772
  sha256: sha,
773
+ sha: sha.slice(0, 16),
748
774
  cdnUrl: this.urlFor(presign.asset, this.defaultPresetForMime(mime))
749
775
  };
750
776
  }
@@ -787,6 +813,7 @@ var NitidaClient = class {
787
813
  return {
788
814
  assetId,
789
815
  sha256: sha,
816
+ sha: sha.slice(0, 16),
790
817
  cdnUrl: this.urlFor(final, this.bestPresetForAsset(final, mime))
791
818
  };
792
819
  }
@@ -800,12 +827,30 @@ var NitidaClient = class {
800
827
  * `presets` string. Falls back through the preference order
801
828
  * lg → md → sm → thumb → original (for images)
802
829
  * video → poster (for videos)
803
- * mp3original (for audio)
830
+ * originalmp3 (for audio ALREADY playable everywhere)
831
+ * mp3 → original (for any other audio)
804
832
  * so an upload that was processed with e.g. `["original"]` still
805
833
  * returns a non-404 URL in `aq.upload`'s result.
834
+ *
835
+ * ⭐ Why audio branches on the source mime (changed 2026-08-22).
836
+ *
837
+ * It used to be `mp3 → original` unconditionally, so `upload().cdnUrl`
838
+ * handed back the server's auto-generated mp3 — libmp3lame, mono ~96 kbps —
839
+ * even when the caller had uploaded an MP3 or an AAC that already plays in
840
+ * every target browser. A consumer asking for "my file" silently received a
841
+ * re-encoded, lower-quality one, with no error to notice.
842
+ *
843
+ * Measured across the platform: of 126 audio assets carrying an mp3 variant,
844
+ * **105 had an `audio/mpeg` source** — an MP3 re-encoded into an MP3, for
845
+ * zero compatibility gain.
846
+ *
847
+ * The mp3 still wins for `audio/webm`/Opus and anything exotic, which is the
848
+ * case it was built for: Chrome records webm/Opus, which iOS Safari cannot
849
+ * decode. That guarantee is preserved exactly; only the needless downgrade
850
+ * is gone.
806
851
  */
807
852
  bestPresetForAsset(asset, mime) {
808
- const order = mime.startsWith("video/") ? ["video", "poster"] : mime.startsWith("audio/") ? ["mp3", "original"] : ["lg", "md", "sm", "thumb", "xl", "original"];
853
+ const order = mime.startsWith("video/") ? ["video", "poster"] : mime.startsWith("audio/") ? isUniversallyPlayableAudio(mime) ? ["original", "mp3"] : ["mp3", "original"] : ["lg", "md", "sm", "thumb", "xl", "original"];
809
854
  return order.find((p) => hasPreset(asset, p)) ?? this.defaultPresetForMime(mime);
810
855
  }
811
856
  };
@@ -879,12 +924,16 @@ export {
879
924
  PRESET_MAX_DIM,
880
925
  PRESET_SHORT,
881
926
  TRANSFORM_WIDTHS,
927
+ accessMessage,
928
+ assertPublic,
929
+ assertSha,
882
930
  bestTextContrast,
883
931
  compressImage,
884
932
  compressImages,
885
933
  computeVariantDimensions,
886
934
  configureSlotResolver2 as configureSlotResolver,
887
935
  contrastRatio,
936
+ deriveAccessKey,
888
937
  extractAssetSha,
889
938
  getAmbientGradient,
890
939
  getAssetDimensions,
@@ -895,6 +944,8 @@ export {
895
944
  getHlsStreamingUrl2 as getHlsStreamingUrl,
896
945
  getPaletteBlurBackground,
897
946
  getPaletteCssVars,
947
+ getPrivateAssetUrl,
948
+ getPrivateTransformUrl,
898
949
  getSignedTransformUrl2 as getSignedTransformUrl,
899
950
  getTenantId,
900
951
  getTextColorForBackground,
@@ -904,6 +955,7 @@ export {
904
955
  hasPreset2 as hasPreset,
905
956
  hlsLadderAlignment,
906
957
  invalidateSlotCache2 as invalidateSlotCache,
958
+ isUniversallyPlayableAudio,
907
959
  iteratePaletteSwatches,
908
960
  mimeFromFileName,
909
961
  pickAmbientBackground,
@@ -913,6 +965,7 @@ export {
913
965
  serializeTransform,
914
966
  setCdnBase2 as setCdnBase,
915
967
  setTenantId2 as setTenantId,
968
+ signAccessUrl,
916
969
  signTransformUrl
917
970
  };
918
971
  //# sourceMappingURL=web.js.map