@nitida/asset-client 0.18.0 → 0.18.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/index.cjs +18 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/access.ts +32 -0
- package/src/index.ts +11 -0
- package/src/transform.ts +6 -1
package/dist/index.d.cts
CHANGED
|
@@ -85,6 +85,29 @@ declare function assertPublic(asset: VisibilityHint, fn: string,
|
|
|
85
85
|
* `getPrivateAssetUrl` for all seven builders; a test caught it.
|
|
86
86
|
*/
|
|
87
87
|
escape: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* Refuse a value whose `sha` is missing or malformed, instead of interpolating
|
|
90
|
+
* it into a URL.
|
|
91
|
+
*
|
|
92
|
+
* ## Found by a Haiku agent, 2026-08-23
|
|
93
|
+
*
|
|
94
|
+
* It did the most natural thing there is — passed the result of `upload()`
|
|
95
|
+
* straight to `transform()` — and got:
|
|
96
|
+
*
|
|
97
|
+
* https://8ok.uk/t/width=1280/undefined.webp
|
|
98
|
+
*
|
|
99
|
+
* `UploadResult` carries `sha256`; every URL builder wants `sha`. TypeScript
|
|
100
|
+
* catches the mismatch, but an agent running through `bun` (or anyone in plain
|
|
101
|
+
* JS) sees no error at all: just a 200-shaped URL with the word `undefined` in
|
|
102
|
+
* it, which 404s later and somewhere else.
|
|
103
|
+
*
|
|
104
|
+
* The house rule applies exactly as it does to private assets: **a silence
|
|
105
|
+
* reads as "you can't"**. A builder that cannot name the asset must say so at
|
|
106
|
+
* the call site, not hand back a string that will fail far from here.
|
|
107
|
+
*/
|
|
108
|
+
declare function assertSha(asset: {
|
|
109
|
+
sha?: unknown;
|
|
110
|
+
}, fn: string): void;
|
|
88
111
|
|
|
89
112
|
/**
|
|
90
113
|
* Color palette helpers — render harmonious ambient backgrounds behind
|
|
@@ -889,4 +912,4 @@ declare function getAssetDimensions(asset: Pick<AssetDTO, "w" | "h">): {
|
|
|
889
912
|
height: number;
|
|
890
913
|
} | null;
|
|
891
914
|
|
|
892
|
-
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, 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 };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -85,6 +85,29 @@ declare function assertPublic(asset: VisibilityHint, fn: string,
|
|
|
85
85
|
* `getPrivateAssetUrl` for all seven builders; a test caught it.
|
|
86
86
|
*/
|
|
87
87
|
escape: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* Refuse a value whose `sha` is missing or malformed, instead of interpolating
|
|
90
|
+
* it into a URL.
|
|
91
|
+
*
|
|
92
|
+
* ## Found by a Haiku agent, 2026-08-23
|
|
93
|
+
*
|
|
94
|
+
* It did the most natural thing there is — passed the result of `upload()`
|
|
95
|
+
* straight to `transform()` — and got:
|
|
96
|
+
*
|
|
97
|
+
* https://8ok.uk/t/width=1280/undefined.webp
|
|
98
|
+
*
|
|
99
|
+
* `UploadResult` carries `sha256`; every URL builder wants `sha`. TypeScript
|
|
100
|
+
* catches the mismatch, but an agent running through `bun` (or anyone in plain
|
|
101
|
+
* JS) sees no error at all: just a 200-shaped URL with the word `undefined` in
|
|
102
|
+
* it, which 404s later and somewhere else.
|
|
103
|
+
*
|
|
104
|
+
* The house rule applies exactly as it does to private assets: **a silence
|
|
105
|
+
* reads as "you can't"**. A builder that cannot name the asset must say so at
|
|
106
|
+
* the call site, not hand back a string that will fail far from here.
|
|
107
|
+
*/
|
|
108
|
+
declare function assertSha(asset: {
|
|
109
|
+
sha?: unknown;
|
|
110
|
+
}, fn: string): void;
|
|
88
111
|
|
|
89
112
|
/**
|
|
90
113
|
* Color palette helpers — render harmonious ambient backgrounds behind
|
|
@@ -889,4 +912,4 @@ declare function getAssetDimensions(asset: Pick<AssetDTO, "w" | "h">): {
|
|
|
889
912
|
height: number;
|
|
890
913
|
} | null;
|
|
891
914
|
|
|
892
|
-
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, 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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -67,6 +67,14 @@ function assertPublic(asset, fn, escape) {
|
|
|
67
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.`
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
|
+
function assertSha(asset, fn) {
|
|
71
|
+
const sha = asset?.sha;
|
|
72
|
+
if (typeof sha === "string" && /^[0-9a-f]{16,64}$/i.test(sha)) return;
|
|
73
|
+
const hint = asset && typeof asset === "object" && "sha256" in asset ? " The value you passed has `sha256` but not `sha` \u2014 that is the shape `upload()` returns. Use `{ sha: result.sha256.slice(0, 16) }`, or fetch the DTO with `assets.get(id)`." : ` Got ${JSON.stringify(sha)}.`;
|
|
74
|
+
throw new Error(
|
|
75
|
+
`${fn}: no usable \`sha\` on the value you passed, so the URL would contain "undefined" and 404 somewhere else.${hint}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
70
78
|
|
|
71
79
|
// src/palette.ts
|
|
72
80
|
function resolveSwatch(palette, ...keys) {
|
|
@@ -243,6 +251,7 @@ function extForOptions(opts) {
|
|
|
243
251
|
}
|
|
244
252
|
}
|
|
245
253
|
function getVideoTransformUrl(asset, opts) {
|
|
254
|
+
assertSha(asset, "getVideoTransformUrl");
|
|
246
255
|
assertPublic(
|
|
247
256
|
asset,
|
|
248
257
|
"getVideoTransformUrl",
|
|
@@ -254,6 +263,7 @@ function getVideoTransformUrl(asset, opts) {
|
|
|
254
263
|
return `${getCdnBase()}/t/${dsl}/${asset.sha}.${ext}`;
|
|
255
264
|
}
|
|
256
265
|
function getHlsStreamingUrl(asset, opts = {}) {
|
|
266
|
+
assertSha(asset, "getHlsStreamingUrl");
|
|
257
267
|
assertPublic(
|
|
258
268
|
asset,
|
|
259
269
|
"getHlsStreamingUrl",
|
|
@@ -270,6 +280,7 @@ function buildTransformUrl(asset, opts) {
|
|
|
270
280
|
return `${getCdnBase()}/t/${dsl}/${asset.sha}.${ext}`;
|
|
271
281
|
}
|
|
272
282
|
function getTransformUrl(asset, opts) {
|
|
283
|
+
assertSha(asset, "getTransformUrl");
|
|
273
284
|
assertPublic(
|
|
274
285
|
asset,
|
|
275
286
|
"getTransformUrl",
|
|
@@ -278,6 +289,7 @@ function getTransformUrl(asset, opts) {
|
|
|
278
289
|
return buildTransformUrl(asset, opts);
|
|
279
290
|
}
|
|
280
291
|
function getSignedTransformUrl(asset, opts, signingKey) {
|
|
292
|
+
assertSha(asset, "getSignedTransformUrl");
|
|
281
293
|
assertPublic(
|
|
282
294
|
asset,
|
|
283
295
|
"getSignedTransformUrl",
|
|
@@ -313,6 +325,7 @@ async function hmacSha256Hex(key, message) {
|
|
|
313
325
|
return [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
314
326
|
}
|
|
315
327
|
function getTransformSrcSet(asset, widths, extraOpts = {}) {
|
|
328
|
+
assertSha(asset, "getTransformSrcSet");
|
|
316
329
|
assertPublic(
|
|
317
330
|
asset,
|
|
318
331
|
"getTransformSrcSet",
|
|
@@ -546,6 +559,7 @@ function originalExtForMime(mime) {
|
|
|
546
559
|
return (mime ? ORIGINAL_EXT_BY_MIME[mime] : void 0) ?? PRESET_EXT.original;
|
|
547
560
|
}
|
|
548
561
|
function getAssetUrl(asset, preset) {
|
|
562
|
+
assertSha(asset, "getAssetUrl");
|
|
549
563
|
assertPublic(
|
|
550
564
|
asset,
|
|
551
565
|
"getAssetUrl",
|
|
@@ -563,6 +577,7 @@ function transformFallbackFor(asset, preset) {
|
|
|
563
577
|
return `${cdnBaseUrl}/t/format=webp,width=${maxDim}/${asset.sha}.webp`;
|
|
564
578
|
}
|
|
565
579
|
function buildPublicAssetUrl(asset, preset) {
|
|
580
|
+
assertSha(asset, "getPrivateAssetUrl");
|
|
566
581
|
if (preset === "original") {
|
|
567
582
|
const stored = asset.variants?.find((v) => v.preset === "original")?.url;
|
|
568
583
|
if (stored) return stored;
|
|
@@ -604,6 +619,7 @@ function stripMultiCharTokens(presets) {
|
|
|
604
619
|
}
|
|
605
620
|
var IMAGE_PRESETS = ["thumb", "sm", "md", "lg", "xl"];
|
|
606
621
|
function getAssetSrcSet(asset) {
|
|
622
|
+
assertSha(asset, "getAssetSrcSet");
|
|
607
623
|
assertPublic(
|
|
608
624
|
asset,
|
|
609
625
|
"getAssetSrcSet",
|
|
@@ -636,6 +652,7 @@ export {
|
|
|
636
652
|
TRANSFORM_WIDTHS,
|
|
637
653
|
accessMessage,
|
|
638
654
|
assertPublic,
|
|
655
|
+
assertSha,
|
|
639
656
|
bestTextContrast,
|
|
640
657
|
computeVariantDimensions,
|
|
641
658
|
configureSlotResolver,
|