@nitida/asset-client 0.18.1 → 0.19.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/dist/index.d.cts CHANGED
@@ -26,6 +26,20 @@
26
26
  *
27
27
  * A signed URL that never expires is a public URL as soon as someone forwards
28
28
  * it. There is no "no expiry" option here, and there will not be one.
29
+ *
30
+ * ## Where `signingKey` comes from
31
+ *
32
+ * The response that created your project. `POST /admin/projects` returns
33
+ * `signingKey` next to the three API keys, and the console shows it in the
34
+ * same panel — **once**. Save it with the keys.
35
+ *
36
+ * If it is gone — or you never saw one, which is the case for every project
37
+ * created before 2026-08-23 — the only endpoint that returns a key is
38
+ * `POST /admin/projects/:code/rotate-signing-key`, and rotating invalidates
39
+ * every URL already signed. That is free for a tenant with nothing in flight
40
+ * and expensive for a live one, which is exactly why the key is handed over at
41
+ * creation, when rotating would be free anyway. With URLs already circulating,
42
+ * ask the platform operator for the current key rather than rotating.
29
43
  */
30
44
  /**
31
45
  * The per-tenant access key, derived from `signing_key`. Same value the origin
@@ -79,12 +93,18 @@ declare function assertPublic(asset: VisibilityHint, fn: string,
79
93
  /**
80
94
  * The call to make instead — declared per call site, not guessed.
81
95
  *
96
+ * Named `escapeHatch`, not `escape`: the bare name shadows the deprecated
97
+ * global `escape`, which biome flags as an error. Nothing here calls that
98
+ * global, so this was never a defect — but it is a lint error standing in a
99
+ * PUBLISHED package, and a parameter name is not part of the API, so the
100
+ * cost of clearing it is zero.
101
+ *
82
102
  * It matters which one: `getPrivateAssetUrl` signs a STORED preset, and
83
103
  * pointing a transform caller at it sends them to a function that cannot do
84
104
  * what they asked for. The first version of this message named
85
105
  * `getPrivateAssetUrl` for all seven builders; a test caught it.
86
106
  */
87
- escape: string): void;
107
+ escapeHatch: string): void;
88
108
  /**
89
109
  * Refuse a value whose `sha` is missing or malformed, instead of interpolating
90
110
  * it into a URL.
@@ -569,6 +589,38 @@ type VariantPreset = "thumb" | "sm" | "md" | "lg" | "xl" | "original" | "poster"
569
589
  * no drift between them.
570
590
  */
571
591
  type RequestablePreset = Exclude<VariantPreset, "hls" | "mp3"> | "probe";
592
+ /**
593
+ * The same set as {@link RequestablePreset}, at RUNTIME.
594
+ *
595
+ * The type stops the mistake in TypeScript. It cannot stop it anywhere else,
596
+ * and "anywhere else" is where it keeps happening: a preset list assembled
597
+ * from config, from a route body, from JSON, or from a script's argv arrives
598
+ * as `string[]`, and the only way past the type was a cast.
599
+ *
600
+ * Measured in neo-real-estate on 2026-08-23, in THREE independent files:
601
+ *
602
+ * presets: [...opts.presets] as VariantPreset[]
603
+ *
604
+ * — a blind cast, and to the wrong type at that: `VariantPreset` includes
605
+ * `hls` and `mp3`, which are precisely the two you may not ask for. Every one
606
+ * of those casts would have compiled a request the server answers 400.
607
+ *
608
+ * So the narrowing lives here, once, instead of being re-invented per repo.
609
+ */
610
+ declare const REQUESTABLE_PRESETS: readonly RequestablePreset[];
611
+ /** Type guard for a single value. */
612
+ declare const isRequestablePreset: (v: string) => v is RequestablePreset;
613
+ /**
614
+ * Narrow a `string[]` to the presets the server can actually produce, or throw
615
+ * naming the offender.
616
+ *
617
+ * Throws rather than filtering silently, for the same reason the seven URL
618
+ * builders throw on a private asset: **a silence reads as "you can't"**. A
619
+ * caller that asked for `hls` wants an HLS ladder; dropping it quietly returns
620
+ * a 200 and no ladder, and the 404 lands later and somewhere else. The error
621
+ * names the value, says why the server cannot make it, and lists what it can.
622
+ */
623
+ declare const toRequestablePresets: (input: readonly string[]) => RequestablePreset[];
572
624
  /** 1-char alias used in storage keys / wire `presets` string. */
573
625
  declare const PRESET_SHORT: Record<VariantPreset, string>;
574
626
  declare const PRESET_LONG: Record<string, VariantPreset>;
@@ -912,4 +964,4 @@ declare function getAssetDimensions(asset: Pick<AssetDTO, "w" | "h">): {
912
964
  height: number;
913
965
  } | null;
914
966
 
915
- export { type AssetDTO, type AssetPalette, type AssetVariant, type HlsRung, PRESET_EXT, PRESET_LONG, PRESET_MAX_DIM, PRESET_SHORT, type PaletteSwatch, type RequestablePreset, type ResolveSlotOptions, type SignAccessOptions, type SignedTransformOptions, type SlotDTO, type SlotResolution, TRANSFORM_WIDTHS, type TransformEffect, type TransformFit, type TransformFormat, type TransformGravity, type TransformOptions, type TransformWidth, type VariantEntryPreset, type VariantPreset, type VisibilityHint, accessMessage, assertPublic, assertSha, bestTextContrast, computeVariantDimensions, configureSlotResolver, contrastRatio, deriveAccessKey, extractAssetSha, getAmbientGradient, getAssetDimensions, getAssetSrcSet, getAssetUrl, getCdnBase, getHlsLadder, getHlsStreamingUrl, getPaletteBlurBackground, getPaletteCssVars, getPrivateAssetUrl, getPrivateTransformUrl, getSignedTransformUrl, getTenantId, getTextColorForBackground, getTransformSrcSet, getTransformUrl, getVideoTransformUrl, hasPreset, hlsLadderAlignment, invalidateSlotCache, iteratePaletteSwatches, pickAmbientBackground, relativeLuminance, resolveSlot, resolveSlots, serializeTransform, setCdnBase, setTenantId, signAccessUrl, signTransformUrl };
967
+ export { type AssetDTO, type AssetPalette, type AssetVariant, type HlsRung, PRESET_EXT, PRESET_LONG, PRESET_MAX_DIM, PRESET_SHORT, type PaletteSwatch, REQUESTABLE_PRESETS, type RequestablePreset, type ResolveSlotOptions, type SignAccessOptions, type SignedTransformOptions, type SlotDTO, type SlotResolution, TRANSFORM_WIDTHS, type TransformEffect, type TransformFit, type TransformFormat, type TransformGravity, type TransformOptions, type TransformWidth, type VariantEntryPreset, type VariantPreset, type VisibilityHint, accessMessage, assertPublic, assertSha, bestTextContrast, computeVariantDimensions, configureSlotResolver, contrastRatio, deriveAccessKey, extractAssetSha, getAmbientGradient, getAssetDimensions, getAssetSrcSet, getAssetUrl, getCdnBase, getHlsLadder, getHlsStreamingUrl, getPaletteBlurBackground, getPaletteCssVars, getPrivateAssetUrl, getPrivateTransformUrl, getSignedTransformUrl, getTenantId, getTextColorForBackground, getTransformSrcSet, getTransformUrl, getVideoTransformUrl, hasPreset, hlsLadderAlignment, invalidateSlotCache, isRequestablePreset, iteratePaletteSwatches, pickAmbientBackground, relativeLuminance, resolveSlot, resolveSlots, serializeTransform, setCdnBase, setTenantId, signAccessUrl, signTransformUrl, toRequestablePresets };
package/dist/index.d.ts CHANGED
@@ -26,6 +26,20 @@
26
26
  *
27
27
  * A signed URL that never expires is a public URL as soon as someone forwards
28
28
  * it. There is no "no expiry" option here, and there will not be one.
29
+ *
30
+ * ## Where `signingKey` comes from
31
+ *
32
+ * The response that created your project. `POST /admin/projects` returns
33
+ * `signingKey` next to the three API keys, and the console shows it in the
34
+ * same panel — **once**. Save it with the keys.
35
+ *
36
+ * If it is gone — or you never saw one, which is the case for every project
37
+ * created before 2026-08-23 — the only endpoint that returns a key is
38
+ * `POST /admin/projects/:code/rotate-signing-key`, and rotating invalidates
39
+ * every URL already signed. That is free for a tenant with nothing in flight
40
+ * and expensive for a live one, which is exactly why the key is handed over at
41
+ * creation, when rotating would be free anyway. With URLs already circulating,
42
+ * ask the platform operator for the current key rather than rotating.
29
43
  */
30
44
  /**
31
45
  * The per-tenant access key, derived from `signing_key`. Same value the origin
@@ -79,12 +93,18 @@ declare function assertPublic(asset: VisibilityHint, fn: string,
79
93
  /**
80
94
  * The call to make instead — declared per call site, not guessed.
81
95
  *
96
+ * Named `escapeHatch`, not `escape`: the bare name shadows the deprecated
97
+ * global `escape`, which biome flags as an error. Nothing here calls that
98
+ * global, so this was never a defect — but it is a lint error standing in a
99
+ * PUBLISHED package, and a parameter name is not part of the API, so the
100
+ * cost of clearing it is zero.
101
+ *
82
102
  * It matters which one: `getPrivateAssetUrl` signs a STORED preset, and
83
103
  * pointing a transform caller at it sends them to a function that cannot do
84
104
  * what they asked for. The first version of this message named
85
105
  * `getPrivateAssetUrl` for all seven builders; a test caught it.
86
106
  */
87
- escape: string): void;
107
+ escapeHatch: string): void;
88
108
  /**
89
109
  * Refuse a value whose `sha` is missing or malformed, instead of interpolating
90
110
  * it into a URL.
@@ -569,6 +589,38 @@ type VariantPreset = "thumb" | "sm" | "md" | "lg" | "xl" | "original" | "poster"
569
589
  * no drift between them.
570
590
  */
571
591
  type RequestablePreset = Exclude<VariantPreset, "hls" | "mp3"> | "probe";
592
+ /**
593
+ * The same set as {@link RequestablePreset}, at RUNTIME.
594
+ *
595
+ * The type stops the mistake in TypeScript. It cannot stop it anywhere else,
596
+ * and "anywhere else" is where it keeps happening: a preset list assembled
597
+ * from config, from a route body, from JSON, or from a script's argv arrives
598
+ * as `string[]`, and the only way past the type was a cast.
599
+ *
600
+ * Measured in neo-real-estate on 2026-08-23, in THREE independent files:
601
+ *
602
+ * presets: [...opts.presets] as VariantPreset[]
603
+ *
604
+ * — a blind cast, and to the wrong type at that: `VariantPreset` includes
605
+ * `hls` and `mp3`, which are precisely the two you may not ask for. Every one
606
+ * of those casts would have compiled a request the server answers 400.
607
+ *
608
+ * So the narrowing lives here, once, instead of being re-invented per repo.
609
+ */
610
+ declare const REQUESTABLE_PRESETS: readonly RequestablePreset[];
611
+ /** Type guard for a single value. */
612
+ declare const isRequestablePreset: (v: string) => v is RequestablePreset;
613
+ /**
614
+ * Narrow a `string[]` to the presets the server can actually produce, or throw
615
+ * naming the offender.
616
+ *
617
+ * Throws rather than filtering silently, for the same reason the seven URL
618
+ * builders throw on a private asset: **a silence reads as "you can't"**. A
619
+ * caller that asked for `hls` wants an HLS ladder; dropping it quietly returns
620
+ * a 200 and no ladder, and the 404 lands later and somewhere else. The error
621
+ * names the value, says why the server cannot make it, and lists what it can.
622
+ */
623
+ declare const toRequestablePresets: (input: readonly string[]) => RequestablePreset[];
572
624
  /** 1-char alias used in storage keys / wire `presets` string. */
573
625
  declare const PRESET_SHORT: Record<VariantPreset, string>;
574
626
  declare const PRESET_LONG: Record<string, VariantPreset>;
@@ -912,4 +964,4 @@ declare function getAssetDimensions(asset: Pick<AssetDTO, "w" | "h">): {
912
964
  height: number;
913
965
  } | null;
914
966
 
915
- export { type AssetDTO, type AssetPalette, type AssetVariant, type HlsRung, PRESET_EXT, PRESET_LONG, PRESET_MAX_DIM, PRESET_SHORT, type PaletteSwatch, type RequestablePreset, type ResolveSlotOptions, type SignAccessOptions, type SignedTransformOptions, type SlotDTO, type SlotResolution, TRANSFORM_WIDTHS, type TransformEffect, type TransformFit, type TransformFormat, type TransformGravity, type TransformOptions, type TransformWidth, type VariantEntryPreset, type VariantPreset, type VisibilityHint, accessMessage, assertPublic, assertSha, bestTextContrast, computeVariantDimensions, configureSlotResolver, contrastRatio, deriveAccessKey, extractAssetSha, getAmbientGradient, getAssetDimensions, getAssetSrcSet, getAssetUrl, getCdnBase, getHlsLadder, getHlsStreamingUrl, getPaletteBlurBackground, getPaletteCssVars, getPrivateAssetUrl, getPrivateTransformUrl, getSignedTransformUrl, getTenantId, getTextColorForBackground, getTransformSrcSet, getTransformUrl, getVideoTransformUrl, hasPreset, hlsLadderAlignment, invalidateSlotCache, iteratePaletteSwatches, pickAmbientBackground, relativeLuminance, resolveSlot, resolveSlots, serializeTransform, setCdnBase, setTenantId, signAccessUrl, signTransformUrl };
967
+ export { type AssetDTO, type AssetPalette, type AssetVariant, type HlsRung, PRESET_EXT, PRESET_LONG, PRESET_MAX_DIM, PRESET_SHORT, type PaletteSwatch, REQUESTABLE_PRESETS, type RequestablePreset, type ResolveSlotOptions, type SignAccessOptions, type SignedTransformOptions, type SlotDTO, type SlotResolution, TRANSFORM_WIDTHS, type TransformEffect, type TransformFit, type TransformFormat, type TransformGravity, type TransformOptions, type TransformWidth, type VariantEntryPreset, type VariantPreset, type VisibilityHint, accessMessage, assertPublic, assertSha, bestTextContrast, computeVariantDimensions, configureSlotResolver, contrastRatio, deriveAccessKey, extractAssetSha, getAmbientGradient, getAssetDimensions, getAssetSrcSet, getAssetUrl, getCdnBase, getHlsLadder, getHlsStreamingUrl, getPaletteBlurBackground, getPaletteCssVars, getPrivateAssetUrl, getPrivateTransformUrl, getSignedTransformUrl, getTenantId, getTextColorForBackground, getTransformSrcSet, getTransformUrl, getVideoTransformUrl, hasPreset, hlsLadderAlignment, invalidateSlotCache, isRequestablePreset, iteratePaletteSwatches, pickAmbientBackground, relativeLuminance, resolveSlot, resolveSlots, serializeTransform, setCdnBase, setTenantId, signAccessUrl, signTransformUrl, toRequestablePresets };
package/dist/index.js CHANGED
@@ -61,10 +61,10 @@ async function signAccessUrl(publicUrl, signingKey, opts) {
61
61
  u.searchParams.set("sig", sig);
62
62
  return u.toString();
63
63
  }
64
- function assertPublic(asset, fn, escape) {
64
+ function assertPublic(asset, fn, escapeHatch) {
65
65
  if (asset.visibility !== "private") return;
66
66
  throw new Error(
67
- `${fn}: this asset is private, so a public CDN URL for it will answer 404 \u2014 that is the feature, not a missing file. Mint a signed URL on your BACKEND instead: await ${escape}. Never ship the signing key to a browser.`
67
+ `${fn}: this asset is private, so a public CDN URL for it will answer 404 \u2014 that is the feature, not a missing file. Mint a signed URL on your BACKEND instead: await ${escapeHatch}. Never ship the signing key to a browser.`
68
68
  );
69
69
  }
70
70
  function assertSha(asset, fn) {
@@ -434,6 +434,28 @@ function materializeResolution(dto, overridePreset) {
434
434
  }
435
435
 
436
436
  // src/index.ts
437
+ var REQUESTABLE_PRESETS = [
438
+ "thumb",
439
+ "sm",
440
+ "md",
441
+ "lg",
442
+ "xl",
443
+ "original",
444
+ "poster",
445
+ "video",
446
+ "aiproxy",
447
+ "probe"
448
+ ];
449
+ var isRequestablePreset = (v) => REQUESTABLE_PRESETS.includes(v);
450
+ var toRequestablePresets = (input) => {
451
+ const bad = input.filter((p) => !isRequestablePreset(p));
452
+ if (bad.length > 0) {
453
+ throw new Error(
454
+ `Cannot request ${bad.map((b) => `"${b}"`).join(", ")}. \`hls\` and \`mp3\` are things a variant can BE, not things you may ask for \u2014 the server derives them itself (hls when a video is transcoded, mp3 alongside any audio original). Requestable: ${REQUESTABLE_PRESETS.join(", ")}.`
455
+ );
456
+ }
457
+ return input;
458
+ };
437
459
  var PRESET_SHORT = {
438
460
  thumb: "q",
439
461
  sm: "s",
@@ -649,6 +671,7 @@ export {
649
671
  PRESET_LONG,
650
672
  PRESET_MAX_DIM,
651
673
  PRESET_SHORT,
674
+ REQUESTABLE_PRESETS,
652
675
  TRANSFORM_WIDTHS,
653
676
  accessMessage,
654
677
  assertPublic,
@@ -679,6 +702,7 @@ export {
679
702
  hasPreset,
680
703
  hlsLadderAlignment,
681
704
  invalidateSlotCache,
705
+ isRequestablePreset,
682
706
  iteratePaletteSwatches,
683
707
  pickAmbientBackground,
684
708
  relativeLuminance,
@@ -688,6 +712,7 @@ export {
688
712
  setCdnBase,
689
713
  setTenantId,
690
714
  signAccessUrl,
691
- signTransformUrl
715
+ signTransformUrl,
716
+ toRequestablePresets
692
717
  };
693
718
  //# sourceMappingURL=index.js.map