@ultimat3/storage 5.0.1 → 7.0.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/README.md CHANGED
@@ -235,7 +235,7 @@ Inside `pending/` deliberately: an upload nobody ever scanned is still an orphan
235
235
  | `X_STORAGE_QUARANTINED` | `promoteAttachment` on a key nothing has released from `pending/quarantine/` |
236
236
  | `X_NOT_IMPLEMENTED` | S3 user metadata / cache-control; `serverSideEncryption` on either driver |
237
237
  | `X_ENV_MISSING` | core's: S3 credential env vars, or a `localDriver` built outside development where neither `signingSecret` nor `STORAGE_SIGNING_SECRET` holds a secret other than the published `DEV_SIGNING_SECRET` |
238
- | `X_IMAGE_UNSUPPORTED` | core's: an `avif`/`webp` encode, or a source no built-in decoder reads |
238
+ | `X_IMAGE_UNSUPPORTED` | core's: an `avif` encode, or a source no built-in decoder reads |
239
239
  | `X_IMAGE_DECODE_FAILED` | core's: truncated or corrupt image bytes |
240
240
 
241
241
  ## Images
@@ -243,11 +243,14 @@ Inside `pending/` deliberately: an upload nobody ever scanned is still an orphan
243
243
  `variantKey()`, `srcsetDescriptors()`, `fitDimensions()` are pure — `@ultimat3/seo` builds
244
244
  `srcset` from them without decoding a byte.
245
245
 
246
- `transformImage()` and `blurPlaceholder()` are real, over `@ultimat3/core`'s zero-dependency
247
- pipeline. **It encodes `png` and `jpeg`, nothing else** — `avif`/`webp` remain key and `srcset`
248
- math, and asking for their bytes rejects with core's `X_IMAGE_UNSUPPORTED` naming the two that
249
- work; produce them through a CDN or a custom `ImageTransformDriver`. `png` is the only output
250
- that keeps alpha. The encoded size is always exactly `fitDimensions()`, so the `width`/`height`
251
- `@ultimat3/seo` already wrote into the tag match the bytes `contain` fits inside the box, it
252
- does not letterbox to it. `blurPlaceholder()` returns a real 16px-wide PNG `data:` URI.
246
+ `transformImage()` and `blurPlaceholder()` are real, over `@ultimat3/core`'s pipeline, which is
247
+ `Bun.Image` — no `sharp`, no dependency. **It encodes `png`, `jpeg` and `webp`** so the default
248
+ format and the default `.webp` key extension finally agree, and a `srcset` entry can be served
249
+ rather than only named. `avif` remains key and `srcset` math: it needs an OS codec the portable
250
+ backend never uses, so asking for its bytes rejects with core's `X_IMAGE_UNSUPPORTED` naming the
251
+ three that work; produce it through a CDN or a custom `ImageTransformDriver`. `png` and `webp` are
252
+ the outputs that keep alpha. The encoded size is always exactly `fitDimensions()`, so the
253
+ `width`/`height` `@ultimat3/seo` already wrote into the tag match the bytes — `contain` fits inside
254
+ the box, it does not letterbox to it. `blurPlaceholder()` returns a ThumbHash PNG `data:` URI, at
255
+ most 32px on its long edge.
253
256
  `bun test` from `packages/storage`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/storage",
3
- "version": "5.0.1",
3
+ "version": "7.0.0",
4
4
  "description": "Named disks over Bun.file and Bun.s3: safe keys, signed URLs, sniffed uploads",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,6 +31,6 @@
31
31
  "test": "bun test"
32
32
  },
33
33
  "dependencies": {
34
- "@ultimat3/core": "5.0.1"
34
+ "@ultimat3/core": "7.0.0"
35
35
  }
36
36
  }
package/src/image.ts CHANGED
@@ -3,12 +3,7 @@
3
3
  // `<img srcset>` from `srcsetDescriptors()` without decoding a byte, and when it does need the
4
4
  // bytes, `transformImage()` returns exactly the size `fitDimensions()` already promised.
5
5
 
6
- import {
7
- blurDataUrl,
8
- BLUR_PLACEHOLDER_WIDTH as CORE_BLUR_PLACEHOLDER_WIDTH,
9
- probeImage,
10
- transformImageBytes,
11
- } from '@ultimat3/core';
6
+ import { blurDataUrl, probeImage, transformImageBytes } from '@ultimat3/core';
12
7
  import { assertSafeKey, keyExtname } from './path';
13
8
 
14
9
  export const IMAGE_FORMATS = ['avif', 'webp', 'jpeg', 'png'] as const;
@@ -33,8 +28,6 @@ export interface ImageSize {
33
28
 
34
29
  export const DEFAULT_QUALITY = 80;
35
30
  export const DEFAULT_SRCSET_WIDTHS = [320, 640, 960, 1280, 1920] as const;
36
- /** Small enough to inline in HTML; big enough to blur convincingly. Core owns the number. */
37
- export const BLUR_PLACEHOLDER_WIDTH = CORE_BLUR_PLACEHOLDER_WIDTH;
38
31
 
39
32
  const FORMAT_EXTENSIONS: Readonly<Record<ImageFormat, string>> = {
40
33
  avif: 'avif',
@@ -116,10 +109,10 @@ export function fitDimensions(source: ImageSize, transform: ImageTransform): Ima
116
109
  }
117
110
 
118
111
  /**
119
- * Decode, resize, encode — core's pipeline, which encodes **png and jpeg only**. `avif` and
120
- * `webp` stay key/`srcset` math: asking for their bytes rejects with core's
121
- * `X_IMAGE_UNSUPPORTED` (not re-wrapped — one failure, one code), and producing them means a
122
- * CDN or a custom `ImageTransformDriver`. PNG is also the only output that keeps alpha.
112
+ * Decode, resize, encode — core's pipeline, which encodes **png, jpeg and webp**. `avif` stays
113
+ * key/`srcset` math: asking for its bytes rejects with core's `X_IMAGE_UNSUPPORTED` (not
114
+ * re-wrapped — one failure, one code) because it needs an OS codec the portable backend never
115
+ * uses, and producing it means a CDN or a custom `ImageTransformDriver`.
123
116
  *
124
117
  * The output box is `fitDimensions()`, always: that is the size `@ultimat3/seo` has already
125
118
  * written into the `<img>` tag, and bytes that disagreed with it would be the layout shift
@@ -144,5 +137,5 @@ export async function transformImage(
144
137
 
145
138
  /** A `data:` URI small enough to inline as the LQIP behind a real image. Always PNG. */
146
139
  export async function blurPlaceholder(bytes: Uint8Array): Promise<string> {
147
- return blurDataUrl(bytes, BLUR_PLACEHOLDER_WIDTH);
140
+ return blurDataUrl(bytes);
148
141
  }
package/src/index.ts CHANGED
@@ -104,7 +104,6 @@ export type {
104
104
  SrcsetOptions,
105
105
  } from './image';
106
106
  export {
107
- BLUR_PLACEHOLDER_WIDTH,
108
107
  blurPlaceholder,
109
108
  DEFAULT_QUALITY,
110
109
  DEFAULT_SRCSET_WIDTHS,