feat(flyimg): add Flyimg built-in provider#2125
feat(flyimg): add Flyimg built-in provider#2125bernhardberger wants to merge 1 commit intonuxt:mainfrom
Conversation
commit: |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Flyimg image provider and integrates it across the project. Files added/updated: src/runtime/providers/flyimg.ts (new provider implementation and FlyimgOptions), src/provider.ts (BuiltInProviders updated), playground/nuxt.config.ts and playground/app/providers.ts (provider config and samples), docs/content/3.providers/flyimg.md (documentation), tests updated: test/providers.ts, test/nuxt/providers.test.ts (new provider tests), and test/e2e/snapshots/flyimg.json5 (snapshots). No existing public API signatures were removed. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
docs/content/3.providers/flyimg.md (1)
64-71: Document thatfit="outside"is unsupported.The provider implementation (Line 191–193 of
flyimg.ts) emits a dev-time warning forfit="outside". Adding a row to this table noting it's unsupported would save users a debugging step.📝 Suggested addition
| `contain` / `inside` | Scale to fit within the target rectangle preserving aspect ratio (Flyimg default) | | `cover` | Crop to fill the rectangle (`c_1`) | | `fill` | Stretch to fill without preserving aspect ratio (`par_0`) | +| `outside` | **Not supported** — ignored with a dev-time warning |🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/content/3.providers/flyimg.md` around lines 64 - 71, Add a row to the `fit` mapping table in docs/content/3.providers/flyimg.md noting that fit="outside" is unsupported; reference the provider's dev-time warning in flyimg.ts (the code path that emits the warning for `fit="outside"`) and state "unsupported (dev-time warning emitted)" or similar so users know this option isn't supported by Flyimg. Ensure the new row follows the existing table format and aligns with the other entries (`Nuxt Image value` / `Flyimg behaviour`) so the documentation clearly reflects the behavior implemented in the `flyimg.ts` provider.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/runtime/providers/flyimg.ts`:
- Line 175: The local variable modifiers is declared as Record<string, unknown>
but is assigned boolean flags and then passed to operationsGenerator which
expects Partial<Record<string, string | number>>; change the modifiers
declaration to a compatible type (e.g., declare modifiers as
Partial<Record<string, string | number | boolean>>) so it accepts booleans, or
alternatively perform a targeted cast when calling operationsGenerator (cast
modifiers to Partial<Record<string, string | number>>) to satisfy the function
signature; update the declaration or the call involving modifiers and
operationsGenerator to use one of these fixes (refer to the modifiers variable
and the operationsGenerator(...) invocation).
---
Nitpick comments:
In `@docs/content/3.providers/flyimg.md`:
- Around line 64-71: Add a row to the `fit` mapping table in
docs/content/3.providers/flyimg.md noting that fit="outside" is unsupported;
reference the provider's dev-time warning in flyimg.ts (the code path that emits
the warning for `fit="outside"`) and state "unsupported (dev-time warning
emitted)" or similar so users know this option isn't supported by Flyimg. Ensure
the new row follows the existing table format and aligns with the other entries
(`Nuxt Image value` / `Flyimg behaviour`) so the documentation clearly reflects
the behavior implemented in the `flyimg.ts` provider.
5571b11 to
d70c9be
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/runtime/providers/flyimg.ts (1)
106-108: Value mappers for color fields should guard against non-string input.The mappers for
background,textColor, andtextBackgroundcallvalue.startsWith(...)on a value typed asstring, butmodifiersis cast toPartial<Record<string, string | number>>, so a numeric value (e.g.background: 0) would reach the mapper and throw aTypeErrorat runtime.🛡️ Proposed fix
- background: (value: string) => value.startsWith('#') ? value.replace('#', '%23') : value, - textColor: (value: string) => value.startsWith('#') ? value.replace('#', '%23') : value, - textBackground: (value: string) => value.startsWith('#') ? value.replace('#', '%23') : value, + background: (value: string) => typeof value === 'string' && value.startsWith('#') ? value.replace('#', '%23') : value, + textColor: (value: string) => typeof value === 'string' && value.startsWith('#') ? value.replace('#', '%23') : value, + textBackground: (value: string) => typeof value === 'string' && value.startsWith('#') ? value.replace('#', '%23') : value,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/providers/flyimg.ts` around lines 106 - 108, The color mappers background, textColor, and textBackground currently call value.startsWith(...) but modifiers is Partial<Record<string, string | number>>, so non-string values (e.g. numbers) will throw; update each mapper to first check typeof value === 'string' before calling startsWith, and either convert non-string values to strings or return them unchanged (e.g. if string and startsWith('#') replace '#' with '%23', otherwise return value as-is) so numeric inputs no longer cause a TypeError.test/providers.ts (1)
36-242: Consider adding test fixtures forfit='cover'andfit='fill'mappings.The current fixtures validate
contain(no-op) andformatconversion, but two additional non-trivial Flyimg flag mappings produced by thefitswitch are untested:
fit: 'cover'→ should emitc_1(e.g.w_200,h_200,c_1)fit: 'fill'→ should emitpar_0(e.g.w_200,h_200,par_0)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/providers.ts` around lines 36 - 242, Add test fixtures covering fit='cover' and fit='fill' for the Flyimg provider: update the existing test object entries that use args: ['/test.png', { width: 200, height: 200, fit: ... }] and add expected flyimg url strings that include the Flyimg flags c_1 for cover (e.g. include "w_200,h_200,c_1" in the flyimg url) and par_0 for fill (e.g. include "w_200,h_200,par_0" in the flyimg url); ensure these entries mirror the style of the existing fixtures (the flyimg key next to other providers) so the test harness can validate the new mappings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/runtime/providers/flyimg.ts`:
- Around line 197-203: The inverted-default checks currently use strict ===
false which ignores numeric 0 values (e.g., strip: 0); update the checks for
strip, mozjpeg, preserveAspectRatio, and preserveNaturalSize so they detect
explicit “off” values including 0 — e.g., guard against null/undefined then
treat falsy 0/false as opt-out — and set the corresponding properties on the
modifiers object (modifiers.strip, modifiers.mozjpeg,
modifiers.preserveAspectRatio, modifiers.preserveNaturalSize) when the caller
explicitly disables them.
---
Nitpick comments:
In `@src/runtime/providers/flyimg.ts`:
- Around line 106-108: The color mappers background, textColor, and
textBackground currently call value.startsWith(...) but modifiers is
Partial<Record<string, string | number>>, so non-string values (e.g. numbers)
will throw; update each mapper to first check typeof value === 'string' before
calling startsWith, and either convert non-string values to strings or return
them unchanged (e.g. if string and startsWith('#') replace '#' with '%23',
otherwise return value as-is) so numeric inputs no longer cause a TypeError.
In `@test/providers.ts`:
- Around line 36-242: Add test fixtures covering fit='cover' and fit='fill' for
the Flyimg provider: update the existing test object entries that use args:
['/test.png', { width: 200, height: 200, fit: ... }] and add expected flyimg url
strings that include the Flyimg flags c_1 for cover (e.g. include
"w_200,h_200,c_1" in the flyimg url) and par_0 for fill (e.g. include
"w_200,h_200,par_0" in the flyimg url); ensure these entries mirror the style of
the existing fixtures (the flyimg key next to other providers) so the test
harness can validate the new mappings.
ce1fff1 to
6f5c0de
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/runtime/providers/flyimg.ts (1)
205-210: Consider a dev warning whensrcis relative butsourceURLis not configured.When
srcis a relative path (e.g.,/images/photo.jpg) andsourceURLis absent,imageUrlretains its leading/. The template literal then produces a double slash (upload/-//images/photo.jpg), whichjoinURLpreserves verbatim, resulting in a malformed Flyimg URL. Flyimg also cannot fetch a relative path regardless. A targeted dev warning would surface this misconfiguration early.💡 Proposed addition
const imageUrl = !hasProtocol(src) && sourceURL ? joinURL(sourceURL, src) : src + +if (import.meta.dev && !hasProtocol(src) && !sourceURL) { + console.warn( + '[nuxt] [image] [flyimg] `src` is a relative path but `sourceURL` is not configured. ' + + 'Flyimg requires an absolute image URL. Set `image.flyimg.sourceURL` in your nuxt.config.', + ) +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/providers/flyimg.ts` around lines 205 - 210, When computing imageUrl, add a developer warning if src is relative (detect via hasProtocol(src) === false) while sourceURL is falsy so we avoid creating malformed Flyimg URLs; specifically, in the same block that computes imageUrl (symbols: src, hasProtocol, sourceURL, joinURL, imageUrl) emit a dev-only console.warn or logger.warn indicating "relative src provided but sourceURL not configured — Flyimg requires absolute URLs" and return or fall back safely (e.g., skip processing or normalize) so callers know the configuration is incorrect.test/providers.ts (1)
36-242: Missing test cases forfit: 'cover'andfit: 'fill'— the two modes that actually emit extra Flyimg flags.The current fixtures only exercise
contain(which is a no-op) andjpegformat. Neithercover(c_1) norfill(par_0) has a snapshot, so a regression in those switch branches would go undetected.💡 Suggested additions to the image fixture array
// After the existing { args: ['/test.png', { width: 200, height: 200, fit: 'contain' }], ... } block: + { + args: ['/test.png', { width: 200, height: 200, fit: 'cover' }], + // ... other providers ... + flyimg: { url: 'https://demo.flyimg.io/upload/w_200,h_200,c_1/https://my-website.com/test.png' }, + }, + { + args: ['/test.png', { width: 200, height: 200, fit: 'fill' }], + // ... other providers ... + flyimg: { url: 'https://demo.flyimg.io/upload/w_200,h_200,par_0/https://my-website.com/test.png' }, + },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/providers.ts` around lines 36 - 242, The test fixtures are missing cases for fit: 'cover' and fit: 'fill' so changes to the Flyimg branch (which emits extra flags) aren't validated; add two new entries in the same fixtures array structure (objects with an args entry and per-provider expectations) targeting the flyimg provider key: one with args ['/test.png', { width: 200, height: 200, fit: 'cover' }] that expects a flyimg URL containing the c_1 flag (e.g. upload/w_200,h_200,o_... including c_1) and one with args ['/test.png', { width: 200, height: 200, fit: 'fill' }] that expects a flyimg URL containing the par_0 flag; place these next to the existing contain/jpeg fixtures so the snapshot tests will cover the Flyimg-specific branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/runtime/providers/flyimg.ts`:
- Around line 197-203: The current checks use strict === false which drops
numeric 0 values (Flyimg uses 0/1), so update the conditional checks for the
inverted-default flags (strip, mozjpeg, preserveAspectRatio,
preserveNaturalSize) to treat explicit false, numeric 0 and string "0" as
disabling values; e.g. for each of
strip/mozjpeg/preserveAspectRatio/preserveNaturalSize, replace the single strict
check with a compound check (value === false || value === 0 || value === '0')
and then set the corresponding
modifiers.strip/modifiers.mozjpeg/modifiers.preserveAspectRatio/modifiers.preserveNaturalSize
= false when that condition is met.
---
Nitpick comments:
In `@src/runtime/providers/flyimg.ts`:
- Around line 205-210: When computing imageUrl, add a developer warning if src
is relative (detect via hasProtocol(src) === false) while sourceURL is falsy so
we avoid creating malformed Flyimg URLs; specifically, in the same block that
computes imageUrl (symbols: src, hasProtocol, sourceURL, joinURL, imageUrl) emit
a dev-only console.warn or logger.warn indicating "relative src provided but
sourceURL not configured — Flyimg requires absolute URLs" and return or fall
back safely (e.g., skip processing or normalize) so callers know the
configuration is incorrect.
In `@test/providers.ts`:
- Around line 36-242: The test fixtures are missing cases for fit: 'cover' and
fit: 'fill' so changes to the Flyimg branch (which emits extra flags) aren't
validated; add two new entries in the same fixtures array structure (objects
with an args entry and per-provider expectations) targeting the flyimg provider
key: one with args ['/test.png', { width: 200, height: 200, fit: 'cover' }] that
expects a flyimg URL containing the c_1 flag (e.g. upload/w_200,h_200,o_...
including c_1) and one with args ['/test.png', { width: 200, height: 200, fit:
'fill' }] that expects a flyimg URL containing the par_0 flag; place these next
to the existing contain/jpeg fixtures so the snapshot tests will cover the
Flyimg-specific branches.
6f5c0de to
f71a4be
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
docs/content/3.providers/flyimg.md (1)
18-33: Consider adding an nginxmerge_slashes offnote to the self-hosted setup.When an absolute source image URL is embedded in the Flyimg request path (e.g.,
.../upload/w_300/https://cdn.example.com/img.jpg),merge_slashesisonby default in nginx, which compresses two or more forward slashes into one. This silently corrupts the embeddedhttps://tohttps:/, causing Flyimg to fail to fetch the source image. This is a confirmed problem for nginx users, fixed by addingmerge_slashes off;to the nginx config.A one-liner note in the Self-hosted section would prevent a frustrating deployment failure.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/content/3.providers/flyimg.md` around lines 18 - 33, Add a brief note in the "Self‑hosted" section warning nginx users that nginx's default merge_slashes behavior will collapse the 'https://' embedded in Flyimg request paths (e.g. paths containing baseURL/sourceURL + absolute image URLs) and instruct them to set merge_slashes off in their nginx config to avoid corrupting embedded URLs so Flyimg can fetch source images correctly; reference the flyimg configuration keys baseURL and sourceURL when describing which requests are affected.src/runtime/providers/flyimg.ts (1)
165-221: LGTM — fit mapping, inverted-defaults, and URL construction are correct.The
!= null && !valueguards for inverted-defaults now correctly handle bothfalseand numeric0. ThejoinURLconstruction avoids double-slash normalization by embedding the absoluteimageUrlinside a template string passed as a single argument. The nginxmerge_slashesconcern is a known operational issue for all Flyimg users behind a proxy.Worth noting in the docs: a known Flyimg issue shows that nginx's default
merge_slashes onsetting collapses//in request URIs, corrupting the embeddedhttps://in the image path — fixed by addingmerge_slashes off;to the nginx config, though the Flyimg maintainer notes this is a reverse-proxy configuration issue rather than a Flyimg bug. Since users deploying Flyimg behind nginx will hit this silently, a brief note in the docs Setup section would prevent a hard-to-diagnose failure.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/providers/flyimg.ts` around lines 165 - 221, Add a short note to the docs Setup section explaining the nginx merge_slashes behavior that can collapse the embedded "https://" in the Flyimg path and instruct users to set merge_slashes off; when reverse-proxying Flyimg; reference the Flyimg maintainer guidance and mention this affects requests built like the one produced by joinURL() using imageUrl (the template path `${processType}/${imageOptions}/${imageUrl}`), and also add a one-line inline comment near the joinURL(...) return in the Flyimg provider implementation to point maintainers to the docs note.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/content/3.providers/flyimg.md`:
- Around line 75-86: The example NuxtImg snippet is missing the provider
attribute so it uses the default provider instead of Flyimg; update the NuxtImg
component (NuxtImg) to include provider="flyimg" in its props so the example
explicitly targets the Flyimg provider and yields the documented behavior.
---
Nitpick comments:
In `@docs/content/3.providers/flyimg.md`:
- Around line 18-33: Add a brief note in the "Self‑hosted" section warning nginx
users that nginx's default merge_slashes behavior will collapse the 'https://'
embedded in Flyimg request paths (e.g. paths containing baseURL/sourceURL +
absolute image URLs) and instruct them to set merge_slashes off in their nginx
config to avoid corrupting embedded URLs so Flyimg can fetch source images
correctly; reference the flyimg configuration keys baseURL and sourceURL when
describing which requests are affected.
In `@src/runtime/providers/flyimg.ts`:
- Around line 165-221: Add a short note to the docs Setup section explaining the
nginx merge_slashes behavior that can collapse the embedded "https://" in the
Flyimg path and instruct users to set merge_slashes off; when reverse-proxying
Flyimg; reference the Flyimg maintainer guidance and mention this affects
requests built like the one produced by joinURL() using imageUrl (the template
path `${processType}/${imageOptions}/${imageUrl}`), and also add a one-line
inline comment near the joinURL(...) return in the Flyimg provider
implementation to point maintainers to the docs note.
f71a4be to
0fc3589
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2125 +/- ##
========================================
- Coverage 6.83% 6.63% -0.21%
========================================
Files 80 81 +1
Lines 3729 3861 +132
Branches 142 143 +1
========================================
+ Hits 255 256 +1
- Misses 3424 3555 +131
Partials 50 50 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
0fc3589 to
0f892d9
Compare
0f892d9 to
4852993
Compare
|
fixed all the coderabbit nitpicks and the tests. ready for review now. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
test/nuxt/providers.test.ts (1)
722-741: Suggest adding unit tests for inverted-defaults andprocessType: 'path'.The existing test loop covers dimension/format combos and
fit: 'cover'/'fill'. However the following provider code paths have zero coverage per the Codecov report:
- Inverted-defaults (
strip,mozjpeg,preserveAspectRatio,preserveNaturalSize) — theisDisabledhelper and each conditional at lines 202–205 are untested.processType: 'path'— the path segment substitution is untested.- Absolute
srcwithoutsourceURL— verifies the pass-through branch of theimageUrlresolution.✅ Suggested additions inside the
it('flyimg', …)block+ // inverted-defaults: strip, mozjpeg, preserveAspectRatio, preserveNaturalSize + expect(flyimg().getImage('/test.png', { modifiers: { width: 200, strip: false }, ...providerOptions }, emptyContext)) + .toMatchObject({ url: 'https://demo.flyimg.io/upload/w_200,st_0/https://my-website.com/test.png' }) + + expect(flyimg().getImage('/test.png', { modifiers: { width: 200, mozjpeg: false }, ...providerOptions }, emptyContext)) + .toMatchObject({ url: 'https://demo.flyimg.io/upload/w_200,moz_0/https://my-website.com/test.png' }) + + expect(flyimg().getImage('/test.png', { modifiers: { width: 200, preserveNaturalSize: false }, ...providerOptions }, emptyContext)) + .toMatchObject({ url: 'https://demo.flyimg.io/upload/w_200,pns_0/https://my-website.com/test.png' }) + + // processType: 'path' + expect(flyimg().getImage('/test.png', { modifiers: { width: 200 }, baseURL: 'https://demo.flyimg.io', sourceURL: 'https://my-website.com', processType: 'path' }, emptyContext)) + .toMatchObject({ url: 'https://demo.flyimg.io/path/w_200/https://my-website.com/test.png' }) + + // absolute src — sourceURL is irrelevant + expect(flyimg().getImage('https://cdn.example.com/photo.jpg', { modifiers: { width: 200 }, baseURL: 'https://demo.flyimg.io' }, emptyContext)) + .toMatchObject({ url: 'https://demo.flyimg.io/upload/w_200/https://cdn.example.com/photo.jpg' })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/nuxt/providers.test.ts` around lines 722 - 741, Tests for the flyimg provider are missing coverage for inverted-defaults and path processing; add unit cases that call flyimg().getImage(...) to exercise the isDisabled helper and branches that toggle strip/mozjpeg/preserveAspectRatio/preserveNaturalSize by passing explicit modifiers that invert defaults, add a test where provider options include processType: 'path' to verify path-segment substitution behavior, and add a test with an absolute src and no sourceURL to assert the absolute URL is passed through unchanged; reference getImage, isDisabled, processType and flyimg() when adding these assertions.src/runtime/providers/flyimg.ts (1)
175-175: Redundant double type annotation — use one or the other.The declaration and the
ascast both assert the same type, making one redundant:const modifiers: Partial<Record<string, string | number | boolean>> = { ...rest } as Partial<Record<string, string | number | boolean>>♻️ Proposed fix
- const modifiers: Partial<Record<string, string | number | boolean>> = { ...rest } as Partial<Record<string, string | number | boolean>> + const modifiers: Partial<Record<string, string | number | boolean>> = { ...rest }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/providers/flyimg.ts` at line 175, The declaration for modifiers redundantly repeats the same type twice; update the declaration of modifiers (the const named "modifiers" that spreads "rest") to use a single type assertion by removing the unnecessary "as Partial<Record<string | number | boolean>>" cast (or alternatively remove the explicit ": Partial<Record<string, number | boolean>>" annotation) so only one typing remains and the value is still typed correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/runtime/providers/flyimg.ts`:
- Around line 217-227: The current fallback imageOptions = operations || '-'
produces an invalid Flyimg segment; change the fallback to a valid default
option (e.g., replace '-' with a sensible option string like 'q_75' or
'w_400,q_75') or refactor so when operationsGenerator(modifiers) returns falsy
you omit the options segment entirely before calling joinURL; update the code
around operationsGenerator, imageOptions, and the joinURL call that builds the
return url (using processType, imageUrl, baseURL) so the produced path is a
valid Flyimg options segment (or excludes it) instead of a lone dash.
---
Nitpick comments:
In `@src/runtime/providers/flyimg.ts`:
- Line 175: The declaration for modifiers redundantly repeats the same type
twice; update the declaration of modifiers (the const named "modifiers" that
spreads "rest") to use a single type assertion by removing the unnecessary "as
Partial<Record<string | number | boolean>>" cast (or alternatively remove the
explicit ": Partial<Record<string, number | boolean>>" annotation) so only one
typing remains and the value is still typed correctly.
In `@test/nuxt/providers.test.ts`:
- Around line 722-741: Tests for the flyimg provider are missing coverage for
inverted-defaults and path processing; add unit cases that call
flyimg().getImage(...) to exercise the isDisabled helper and branches that
toggle strip/mozjpeg/preserveAspectRatio/preserveNaturalSize by passing explicit
modifiers that invert defaults, add a test where provider options include
processType: 'path' to verify path-segment substitution behavior, and add a test
with an absolute src and no sourceURL to assert the absolute URL is passed
through unchanged; reference getImage, isDisabled, processType and flyimg() when
adding these assertions.
| // --- Build Flyimg URL -------------------------------------------------- | ||
| const operations = operationsGenerator(modifiers as Partial<Record<string, string | number>>) | ||
| const imageOptions = operations || '-' | ||
|
|
||
| // Construct the path manually so that an absolute imageUrl is treated as a | ||
| // literal path segment rather than a new base by ufo's joinURL. | ||
| // Note: if reverse-proxied via nginx, set `merge_slashes off` to prevent | ||
| // nginx from collapsing the `https://` embedded in this path. See docs. | ||
| return { | ||
| url: joinURL(baseURL || '/', `${processType}/${imageOptions}/${imageUrl}`), | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Flyimg URL format image_options dash parameter support
💡 Result:
Flyimg’s URL format is:
https://<server>/<process-type>/<image_options>/<path_to_image> (e.g. /upload/w_500/...). Image options are comma-separated transformations, and each option is encoded as <key>_<value> (e.g. w_300,h_200,q_85,o_webp). A dash (-) is not a supported separator/“parameter” format for image_options—use underscores between key/value and commas between options. [1], [2]
Sources
[1] Flyimg docs – “URL Options” https://docs.flyimg.io/url-options/
[2] Klutch.sh guide – “Deploying Flyimg” https://docs.klutch.sh/guides/open-source-software/flyimg/
🌐 Web query:
Flyimg upload dash empty options segment https://demo.flyimg.io
💡 Result:
Flyimg’s upload endpoint requires a non-empty “image options” path segment:
https://demo.flyimg.io/upload/{image_options}/{source_image_url} [1][2]
So a URL like:
https://demo.flyimg.io/upload//https://example.com/img.jpg
fails because the {image_options} segment is empty.
Use at least one option, e.g.:
https://demo.flyimg.io/upload/w_800/https://flyimg.io/demo-images/Citroen-DS.jpg[1][2]https://demo.flyimg.io/upload/q_90/https://flyimg.io/demo-images/Citroen-DS.jpg[2]
If you tell me the exact URL you tried (and the exact error text), I can point out the precise fix.
🌐 Web query:
Flyimg option parser behavior underscore key_value parameters
💡 Result:
In Flyimg, the URL “image options” segment is parsed as a list of option tokens (transformations/settings):
- Multiple options are separated by
options_separator(default comma,, configurable inconfig/parameters.yml). (docs.flyimg.io) - Each option token is written as
<key>_<value>(underscore-delimited “key_value”), e.g.w_250,q_50orc_1. (docs.flyimg.io) - Many boolean-ish options are expressed by passing
..._1(e.g.c_1,rf_1). (docs.flyimg.io)
Practical implication: _ is the key/value delimiter inside each token, while options_separator only controls how tokens are split from each other. (docs.flyimg.io)
Citations:
- 1: https://docs.flyimg.io/configuration/
- 2: https://docs.flyimg.io/?utm_source=openai
- 3: https://docs.flyimg.io/url-options/
- 4: https://docs.flyimg.io/configuration/
Replace the fallback - with a valid default option or refactor to handle no-modifier requests differently.
The code at line 219 uses operations || '-' to provide a fallback when no modifiers are provided. However, Flyimg's URL structure requires the image_options segment to contain valid key_value pairs separated by commas (e.g., w_500,q_90). A bare dash has no underscore and is not a recognized option format in Flyimg—it will not be parsed correctly and will produce invalid requests.
Additionally, Flyimg's documentation and tests confirm that a completely empty image_options segment fails (e.g., /upload//https://...). When no modifiers are provided, the code should either:
- Provide a sensible default option (e.g.,
q_75for quality, orw_400for a standard width). - Document what behavior Flyimg exhibits with this malformed option and why it is acceptable.
- Refactor to omit the options segment entirely if Flyimg supports a direct format like
/upload/https://...(verify with Flyimg maintainers if uncertain).
Without a fix, requests without modifiers will generate invalid Flyimg URLs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/runtime/providers/flyimg.ts` around lines 217 - 227, The current fallback
imageOptions = operations || '-' produces an invalid Flyimg segment; change the
fallback to a valid default option (e.g., replace '-' with a sensible option
string like 'q_75' or 'w_400,q_75') or refactor so when
operationsGenerator(modifiers) returns falsy you omit the options segment
entirely before calling joinURL; update the code around operationsGenerator,
imageOptions, and the joinURL call that builds the return url (using
processType, imageUrl, baseURL) so the produced path is a valid Flyimg options
segment (or excludes it) instead of a lone dash.
🔗 Linked issue
No pre-existing issue — this is a straightforward provider addition.
❓ Type of change
📚 Description
This PR adds Flyimg as a built-in provider.
What is Flyimg?
Flyimg is an open-source, self-hosted image processing server built on top of ImageMagick and MozJPEG. It processes images on-the-fly via a URL-based API and caches results in Redis. It can be deployed via Docker and works as a drop-in image CDN for self-hosters.
Background
We've been running Flyimg in production for a while as our image processing layer. I wanted to contribute our provider implementation back to
@nuxt/imageso others can benefit from it without having to write a custom provider.What's included
src/runtime/providers/flyimg.ts— provider implementation with full modifier support (resize, crop, gravity, format conversion, quality, watermarking, text overlays, background color, etc.)docs/content/3.providers/flyimg.md— documentation page with setup instructions for both self-hosted and SaaS deployments, options table, and modifier referencetest/providers.ts+test/nuxt/providers.test.ts— unit tests for URL generationplayground/app/providers.ts+playground/nuxt.config.ts— playground entries for manual testingConfiguration