@uxf/resizer 11.88.0 → 11.123.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.
@@ -1,14 +1,14 @@
1
1
  [
2
- {
3
- "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:extension.:toFormat",
4
- "source": "/Users/vejvis/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
5
- },
6
- {
7
- "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+).:extension",
8
- "source": "/Users/vejvis/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
9
- },
10
- {
11
- "route": "/generated/static/:width(\\d+)_:height(\\d+)/:filename(*).:extension.:toFormat",
12
- "source": "https://www.uxf.cz/:filename+.:extension"
13
- }
14
- ]
2
+ {
3
+ "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:extension.:toFormat",
4
+ "source": "/Users/vejvis/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
5
+ },
6
+ {
7
+ "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+).:extension",
8
+ "source": "/Users/vejvis/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
9
+ },
10
+ {
11
+ "route": "/generated/static/:width(\\d+)_:height(\\d+)/:filename(*).:extension.:toFormat",
12
+ "source": "https://www.uxf.cz/:filename+.:extension"
13
+ }
14
+ ]
package/README.md CHANGED
@@ -1,29 +1,49 @@
1
1
  # @uxf/resizer
2
+
2
3
  [![npm](https://img.shields.io/npm/v/@uxf/resizer)](https://www.npmjs.com/package/@uxf/resizer)
3
4
 
5
+ On-the-fly image resizing that serves the `/generated/...` URLs produced by `resizerImageUrl` (`@uxf/core`). It ships Next.js App Router route handlers for local development and a standalone Express server (`uxf-resizer`) for self-hosting. Resizing is done with [`sharp`](https://sharp.pixelplumbing.com/).
6
+
7
+ ## When to use
8
+
9
+ This package **serves and generates** resized images. It does **not** build image URLs — that is done client-side by `resizerImageUrl` from `@uxf/core/utils/resizer`, which encodes the resize parameters into a `/generated/...` path.
10
+
11
+ - **Production** — a shared/global resizer service handles the `/generated/...` requests; you typically do not run this package there.
12
+ - **Local development** — mount `ProxyGET` / `StaticGET` as Next.js route handlers so `/generated/...` URLs resolve during `next dev`.
13
+ - **Self-hosting** — run the `uxf-resizer` CLI (Express server) driven by a config file.
14
+
15
+ Both entry points read the same URL segments (width, height, fit, position, background, trim, quality, target format) and pipe the source image through `sharp`. Generated files are cached on disk and re-served on subsequent requests.
16
+
17
+ ## Installation
4
18
 
5
- ## Installation + example (local dev next routes)
6
19
  ```
7
20
  yarn add @uxf/resizer --dev
8
21
  ```
9
22
 
10
- ```shell
11
- # .env.local
12
- NEXT_PUBLIC_FRONTEND_URL=http://127.0.0.1:3000
13
- NEXT_PUBLIC_API_URL=https://uxf.cz
23
+ The only runtime dependency is `sharp`. The standalone server additionally needs `express`, `path-to-regexp`, `process`, and `yargs` — they are **not** installed transitively, so add them yourself when you use the CLI:
24
+
25
+ ```
26
+ yarn add @uxf/resizer express path-to-regexp process yargs --dev
14
27
  ```
15
28
 
16
- Folder structure
29
+ ## Quick start
30
+
31
+ Next.js App Router route handlers for local development. Two handlers are exported:
32
+
33
+ - `ProxyGET` — proxies uploaded images from the API and resizes them.
34
+ - `StaticGET` — resizes static assets (`public/` files and Next.js `_next/static/media` imports).
35
+
36
+ Folder structure:
17
37
 
18
38
  ```shell
19
39
  src/
20
40
  app/
21
41
  generated/
22
42
  [...path]/
23
- route.ts # proxy
43
+ route.ts # ProxyGET → uploaded images
24
44
  static/
25
45
  [...path]/
26
- route.ts # local static files
46
+ route.ts # StaticGET static images
27
47
  ```
28
48
 
29
49
  ```ts
@@ -40,49 +60,99 @@ import { StaticGET as GET } from "@uxf/resizer";
40
60
  export { GET };
41
61
  ```
42
62
 
43
- ## Installation (server)
63
+ Both handlers read their upstream location from environment variables:
64
+
65
+ ```shell
66
+ # .env.local
67
+ NEXT_PUBLIC_FRONTEND_URL=http://127.0.0.1:3000 # StaticGET source (Next.js static media)
68
+ NEXT_PUBLIC_API_URL=https://uxf.cz # ProxyGET source (fetches <API_URL>/upload/...)
69
+ ```
70
+
71
+ ## API
72
+
73
+ Exported from the package root (`@uxf/resizer`):
74
+
75
+ | Export | Signature | Description |
76
+ |--------|-----------|-------------|
77
+ | `ProxyGET` | `(request: Request) => Promise<Response>` | Next.js route handler. Matches `/generated/:namespace/:p1/:p2/:filename_..._:extension.:toFormat`, fetches the source from `${NEXT_PUBLIC_API_URL}/upload/:namespace/:p1/:p2/:filename.:extension`, resizes, caches under the process CWD, and returns the image. |
78
+ | `StaticGET` | `(request: Request) => Promise<Response>` | Next.js route handler. Matches `/generated/static/..._:quality/:version/:filename.:extension.:toFormat`. Reads local `public/:filename.:extension`; for `_next/static/media/*` imports it fetches from `${NEXT_PUBLIC_FRONTEND_URL}`. |
79
+
80
+ Command-line server:
81
+
44
82
  ```
45
- yarn add @uxf/resizer express path-to-regexp process yargs
46
83
  uxf-resizer
47
84
  ```
48
85
 
49
- ## Configuration
86
+ Starts an Express server on port `3000` that applies the routes from the configuration (see below). Requires the extra dependencies listed under Installation.
87
+
88
+ ## Route parameters
89
+
90
+ The URL segments understood by every route. They are produced by `resizerImageUrl` (`@uxf/core`) and mapped onto [`sharp`](https://sharp.pixelplumbing.com/) options.
50
91
 
51
- You can use configuration file `.resizer-config.json` or environment variable `UXF_RESIZER_CONFIG`
92
+ | Parameter | Values | Default (falls back to sharp) |
93
+ |------------|--------------------------------------------|----------------------------------------|
94
+ | width | `number` or `x` (auto) | `undefined` (auto) |
95
+ | height | `number` or `x` (auto) | `undefined` (auto) |
96
+ | fit | fit code (see below) | `cover` |
97
+ | position | position code (see below) | sharp default (`centre`) |
98
+ | background | hex (e.g. `FFFFFF`) or `t` (transparent) | `#<hex>` |
99
+ | trim | `number` (threshold) or `nt` (no trim) | no trim |
100
+ | quality | `number` (1–100) or `x` (auto) | sharp default (avif: 50, others: 80) |
101
+ | toFormat | `webp`, `png`, `avif`, `jpg`, `svg` | `jpg` |
102
+
103
+ `svg` is a passthrough — the source file is copied unchanged, without resizing.
104
+
105
+ ### Fit codes
106
+
107
+ - `cv`: cover
108
+ - `f`: fill
109
+ - `cn`: contain
110
+ - `in`: inside
111
+ - `out`: outside
112
+
113
+ ### Position codes
114
+
115
+ - `a`: attention
116
+ - `b`: bottom
117
+ - `c`: centre
118
+ - `e`: entropy
119
+ - `l`: left
120
+ - `lb`: left bottom
121
+ - `lt`: left top
122
+ - `r`: right
123
+ - `rb`: right bottom
124
+ - `rt`: right top
125
+ - `t`: top
126
+
127
+ ## Server configuration
128
+
129
+ The `uxf-resizer` CLI reads its config from `.resizer-config.json` in the working directory, or from the `UXF_RESIZER_CONFIG` environment variable (an inline JSON string, which takes precedence). Generated files are written to `UXF_RESIZER_GENERATE_PATH` (defaults to the process CWD).
130
+
131
+ The config is an array of `{ route, source }` objects. `route` is a [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp) pattern that captures the resize parameters; `source` is the original file location (a local path or an `http(s)` URL, which is fetched). `source` may reference any captured segment, including the domain as a parameter (e.g. `https://:url/...`).
52
132
 
53
133
  ```json
54
134
  [
55
135
  {
56
- "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)_:extension.:toFormat",
57
- "source": "/var/www/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
58
- },
59
- {
60
- "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+)_:height(\\d+)_:fit([a-z]+).:extension",
61
- "source": "/var/www/UXF/projects/resizer/example-upload/:namespace/:p1/:p2/:filename.:extension"
62
- },
63
- {
64
- "route": "/generated/static/:width(\\d+)_:height(\\d+)/:filename(*).:extension.:toExtension",
65
- "source": "https://www.uxf.cz/:filename+"
136
+ "route": "/generated/static/:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)/:version/:filename(*).:extension.:toFormat",
137
+ "source": "https://static.example.dev/:filename+.:extension"
66
138
  },
67
139
  {
68
- "route": "/:appName/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)_:extension.:toFormat",
69
- "source": "https://s3.uxf.dev/:appName/:namespace/:p1/:p2/:filename.:extension"
70
- },
71
- {
72
- "route": "/:url/generated/static/:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)/:version/:filename(*).:extension.:toFormat",
73
- "source": "https://:url/:filename+.:extension"
140
+ "route": "/generated/:namespace/:p1/:p2/:filename([a-f0-9\\-]+)_:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)_:extension.:toFormat",
141
+ "source": "https://s3.example.dev/:namespace/:p1/:p2/:filename.:extension"
74
142
  }
75
143
  ]
76
144
  ```
77
145
 
78
- ### UXF Basic configuration
146
+ `resizerGetDefaultConfig(generatedFilesUrl, staticFilesUrl)` from `@uxf/core/utils/resizer` returns exactly this two-route shape.
79
147
 
80
- This is deprecated. Please use our global resizer for all projects.
148
+ ### UXF Basic configuration (deprecated)
149
+
150
+ Deprecated — use the global resizer for all projects instead.
81
151
 
82
152
  ```json
83
153
  [
84
154
  {
85
- "route": "/generated/static/:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)/:version/:filename(*).:extension.:toFormat",
155
+ "route": "/generated/static/:width(\\d+|x)_:height(\\d+|x)_:fit([a-z]+)_:position([a-z]+)_:background([a-z]+)_:trim([a-z]+)_:quality(\\d+|x)/:version/:filename(*).:extension.:toFormat",
86
156
  "source": "https://uxf-base.uxf.dev/:filename+.:extension"
87
157
  },
88
158
  {
@@ -92,36 +162,16 @@ This is deprecated. Please use our global resizer for all projects.
92
162
  ]
93
163
  ```
94
164
 
95
- ### Supported route parameters
96
-
97
- | Parameter name | Type | Default sharp value |
98
- |----------------|------------------------------------|----------------------------------------|
99
- | width | `number` or `x` (auto) | `undefined` |
100
- | height | `number` or `x` (auto) | `undefined` |
101
- | fit | `Fit` | cover |
102
- | position | `Position` | |
103
- | background | `FFFFFF` or `t` (transparent) | |
104
- | toFormat | `webp`, `png`, `avif`, `jpg` | `jpg` |
105
- | trim | `number` or `nt` (not trim) | |
106
- | quality | `number` (min: 1, max: 100) or `x` | default of sharp (avif: 50, other: 80) |
165
+ ## Gotchas
107
166
 
167
+ - **URLs are built elsewhere.** Encode the parameters with `resizerImageUrl` from `@uxf/core/utils/resizer`; this package only serves the resulting paths.
168
+ - **CLI dependencies are not transitive.** `express`, `path-to-regexp`, `process`, and `yargs` are dev dependencies of this package, so a consumer running `uxf-resizer` must install them explicitly.
169
+ - **Generated files are cached on disk.** Once a variant exists under the output path it is served as-is; delete the cached file to force regeneration.
170
+ - **The server listens on a fixed port `3000`** and an empty or invalid configuration throws on startup.
171
+ - **`quality` defaults to sharp's own defaults** when set to `x` (avif ≈ 50, others ≈ 80). Values are expected in the `1–100` range.
108
172
 
109
- #### Fit
110
- - `cv`: cover,
111
- - `f`: fill,
112
- - `cn`: contain,
113
- - `in`: inside,
114
- - `out`: outside,
173
+ ## Links
115
174
 
116
- #### Position
117
- - `a`: attention
118
- - `b`: bottom
119
- - `c`: centre
120
- - `e`: entropy
121
- - `l`: left
122
- - `lb`: left bottom
123
- - `lt`: left top
124
- - `r`: right
125
- - `rb`: right bottom
126
- - `rt`: right top
127
- - `t`: top
175
+ - [npm: @uxf/resizer](https://www.npmjs.com/package/@uxf/resizer)
176
+ - [sharp documentation](https://sharp.pixelplumbing.com/)
177
+ - URL builder: `resizerImageUrl` in `@uxf/core/utils/resizer`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/resizer",
3
- "version": "11.88.0",
3
+ "version": "11.123.0",
4
4
  "main": "index.js",
5
5
  "description": "UXF Resizer",
6
6
  "author": "UXFans <dev@uxf.cz>",
@@ -19,15 +19,15 @@
19
19
  "sharp": "^0.34.4"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/express": "4.17.21",
23
- "@types/express-serve-static-core": "4.19.6",
22
+ "@types/express": "4.17.25",
23
+ "@types/express-serve-static-core": "4.19.9",
24
24
  "@types/node": "24",
25
- "concurrently": "9.2.1",
25
+ "concurrently": "10.0.4",
26
26
  "crypto-js": "4.2.0",
27
- "express": "4.21.1",
27
+ "express": "4.22.2",
28
28
  "path-to-regexp": "6.2.2",
29
29
  "process": "0.11.10",
30
- "yargs": "18.0.0"
30
+ "yargs": "18.1.0"
31
31
  },
32
32
  "engines": {
33
33
  "node": ">=24"
@@ -35,6 +35,6 @@
35
35
  "scripts": {
36
36
  "build": "tsc -P tsconfig.json",
37
37
  "dev": "tsx ./bin/uxf-resizer.ts",
38
- "typecheck": "tsc --noEmit --skipLibCheck"
38
+ "typecheck": "tsc --noEmit"
39
39
  }
40
40
  }
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "composite": true,
5
- "outDir": "./"
6
- }
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "outDir": "./"
6
+ }
7
7
  }