Repository: nuxt/image
Pull request #1452 (2024-08-28 14:51:21)

fix(hygraph): add back tests and refactor splitter
### 🔗 Linked issue



### ❓ Type of change

<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->

- [ ] 📖 Documentation (updates to the documentation or readme)
- [x] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [ ] 👌 Enhancement (improving an existing functionality)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

### 📚 Description

Following on from https://github.com/nuxt/image/pull/1415/files, this enables the provider tests for `hygraph` and tweaks the splitter implementation.

cc: @timbenniks - is this right?

cloudflare-pages[bot]: ## Deploying nuxt-image with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>3f66332</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://feeeffd6.nuxt-image.pages.dev'>https://feeeffd6.nuxt-image.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://fix-hygraph.nuxt-image.pages.dev'>https://fix-hygraph.nuxt-image.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/nuxt-image/feeeffd6-74b9-4a17-83d5-1709dada9343)


Patch:
diff --git a/docs/content/3.providers/hygraph.md b/docs/content/3.providers/hygraph.md
index 0cd6c9b..cdd2bf8 100644
--- a/docs/content/3.providers/hygraph.md
+++ b/docs/content/3.providers/hygraph.md
@@ -16,7 +16,7 @@ To use this provider you just need to specify the base URL of your project.
 export default defineNuxtConfig({
   image: {
     hygraph: {
-      baseURL: "",
+      baseURL: "https://<subdomain>.graphassets.com/<baseid>",
     },
   },
 });
@@ -29,7 +29,7 @@ All the default modifiers from [Hygraph's documentation](https://hygraph.com/doc
 ```vue
 <NuxtImg
   provider="hygraph"
-  src="https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue"
+  src="/cltsrex89477t08unlckqx9ue"
   height="512"
   width="512"
   fit="max"
diff --git a/src/runtime/providers/hygraph.ts b/src/runtime/providers/hygraph.ts
index 8d50e37..0294851 100644
--- a/src/runtime/providers/hygraph.ts
+++ b/src/runtime/providers/hygraph.ts
@@ -1,4 +1,4 @@
-import { joinURL } from 'ufo'
+import { joinURL, parseURL, withTrailingSlash } from 'ufo'
 import type { ProviderGetImage } from '@nuxt/image'
 
 type ImageOptimizations = {
@@ -9,7 +9,7 @@ type ImageOptimizations = {
   quality?: number
 }
 
-export function getImageFormat(format?: string) {
+function getImageFormat(format?: string) {
   let result = 'auto_image'
 
   if (format && format !== 'auto_image') {
@@ -19,32 +19,40 @@ export function getImageFormat(format?: string) {
   return result
 }
 
-export function splitUpURL(url: string, baseURL: string) {
-  // Starting Image URL: https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue
+const ID_RE = /([^/]+)\/?$/
+const COMBINED_ID_RE = /^\/(?<baseId>[^/]+)(?:\/.*)?\/(?<imageId>[^/]+)$/
 
-  // get Both IDs split off of the baseURL
-  // -> cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue
-  const bothIds = url.split(`${baseURL}/`)[1]
+function splitUpURL(baseURL: string, url: string) {
+  /**
+   * https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue
+   *  - baseId: cltsj3mii0pvd07vwb5cyh1ig
+   *  - imageId: cltsrex89477t08unlckqx9ue
+   */
+  const baseId = parseURL(baseURL).pathname.match(ID_RE)?.[1]
 
-  // get baseId
-  // -> cltsj3mii0pvd07vwb5cyh1ig
-  // @ts-expect-error fixing in separate PR
-  const baseId = bothIds.split('/')[0]
+  if (!baseId) {
+    // extract baseId from url instead
+    url = url.replace(withTrailingSlash(baseURL), '/')
 
-  // get imageId
-  // -> cltsrex89477t08unlckqx9ue
-  const imageId = url.split(`/`)[url.split(`/`).length - 1]
+    const groups = url.match(COMBINED_ID_RE)?.groups
+    if (!groups) {
+      throw new TypeError('[nuxt] [image] [hygraph] Invalid image URL')
+    }
+    return groups as { baseId: string, imageId: string }
+  }
 
-  return {
-    baseId,
-    imageId,
+  const imageId = url.match(ID_RE)?.[0]
+
+  if (!imageId) {
+    throw new TypeError('[nuxt] [image] [hygraph] Invalid image URL')
   }
-}
 
-export function optimizeHygraphImage(baseURL: string, url: string, optimizations: ImageOptimizations) {
-  baseURL = baseURL.replace(/\/+$/, '')
+  // it's already in baseURL so we can omit it here
+  return { baseId: '', imageId }
+}
 
-  const { baseId, imageId } = splitUpURL(url, baseURL)
+function optimizeHygraphImage(baseURL: string, url: string, optimizations: ImageOptimizations) {
+  const { baseId, imageId } = splitUpURL(baseURL, url)
   const imageFormat = getImageFormat(optimizations.format)
   const optimBase = 'resize'
   const quality = optimizations.quality && imageFormat !== 'auto_image' ? `quality=value:${optimizations.quality}/` : ''
@@ -62,23 +70,13 @@ export function optimizeHygraphImage(baseURL: string, url: string, optimizations
   }
 
   const optim = `${optimBase}=${optimList.join(',')}`
-  // @ts-expect-error fixing in separate PR
   const result = joinURL(baseURL, baseId, optim, quality, imageFormat, imageId)
 
   return result
 }
 
-export const getImage: ProviderGetImage = (
-  src,
-  { modifiers = {}, baseURL } = {},
-) => {
-  const {
-    width,
-    height,
-    fit,
-    format,
-    quality,
-  } = modifiers
+export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL } = {}) => {
+  const { width, height, fit, format, quality } = modifiers
 
   if (!baseURL) {
     throw new Error('No Hygraph image base URL provided.')


Test patch:
diff --git a/test/e2e/__snapshots__/hygraph.json5 b/test/e2e/__snapshots__/hygraph.json5
index 44f19a7..a08d29b 100644
--- a/test/e2e/__snapshots__/hygraph.json5
+++ b/test/e2e/__snapshots__/hygraph.json5
@@ -1,12 +1,12 @@
 {
   "requests": [
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:300,height:300,fit:clip/output=format:jpeg/cltsrex89477t08unlckqx9ue",
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:500,fit:max/auto_image/cltsrex89477t08unlckqx9ue",
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:500,height:500,fit:crop/auto_image/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:300,height:300,fit:clip/output=format:jpeg/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:500,fit:max/auto_image/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:500,height:500,fit:crop/auto_image/cltsrex89477t08unlckqx9ue",
   ],
   "sources": [
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:500,height:500,fit:crop/auto_image/cltsrex89477t08unlckqx9ue",
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:500,fit:max/auto_image/cltsrex89477t08unlckqx9ue",
-    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue/resize=width:300,height:300,fit:clip/output=format:jpeg/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:500,height:500,fit:crop/auto_image/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:500,fit:max/auto_image/cltsrex89477t08unlckqx9ue",
+    "https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:300,height:300,fit:clip/output=format:jpeg/cltsrex89477t08unlckqx9ue",
   ],
-}
\ No newline at end of file
+}
diff --git a/test/providers.ts b/test/providers.ts
index 53dafac..7dcabc0 100644
--- a/test/providers.ts
+++ b/test/providers.ts
@@ -30,7 +30,7 @@ export const images = [
     uploadcare: { url: 'https://ucarecdn.com/c160afba-8b42-45a9-a46a-d393248b0072/' },
     weserv: { url: 'https://wsrv.nl/?filename=test.png&we&url=https://my-website.com/test.png' },
     sirv: { url: 'https://demo.sirv.com/test.png' },
-    hygraph: { url: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue' },
+    hygraph: { url: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=/auto_image/cltsrex89477t08unlckqx9ue' },
     caisy: { url: 'https://assets.caisy.io/assets/b76210be-a043-4989-98df-ecaf6c6e68d8/056c27e2-81f5-4cd3-b728-cef181dfe7dc/d83ea6f0-f90a-462c-aebd-b8bc615fdce0pexelsmiguelapadrinan1591056.jpg' },
     bunny: { url: 'https://bunnyoptimizerdemo.b-cdn.net' },
   },
@@ -205,7 +205,7 @@ export const images = [
     uploadcare: { url: 'https://ucarecdn.com/c160afba-8b42-45a9-a46a-d393248b0072/-/format/jpeg/-/resize/200x200/-/stretch/off/' },
     weserv: { url: 'https://wsrv.nl/?filename=test.png&we&w=200&h=200&fit=contain&output=jpg&url=https://my-website.com/test.png' },
     sirv: { url: 'https://demo.sirv.com/test.png?w=200&h=200&scale.option=fit&format=jpg' },
-    hygraph: { url: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:200,height:200,fit:max/output=format:jpg/cltsrex89477t08unlckqx9ue' },
+    hygraph: { url: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/resize=width:200,height:200,fit:max/output=format:jpeg/cltsrex89477t08unlckqx9ue' },
     caisy: { url: 'https://assets.caisy.io/assets/b76210be-a043-4989-98df-ecaf6c6e68d8/056c27e2-81f5-4cd3-b728-cef181dfe7dc/d83ea6f0-f90a-462c-aebd-b8bc615fdce0pexelsmiguelapadrinan1591056.jpg?w=200&h=200' },
     bunny: { url: 'https://bunnyoptimizerdemo.b-cdn.net?width=200&height=200' },
   },
diff --git a/test/unit/providers.test.ts b/test/unit/providers.test.ts
index 9c89f85..7869e54 100644
--- a/test/unit/providers.test.ts
+++ b/test/unit/providers.test.ts
@@ -35,6 +35,7 @@ import * as vercel from '#image/providers/vercel'
 import * as wagtail from '#image/providers/wagtail'
 import * as uploadcare from '#image/providers/uploadcare'
 import * as sirv from '#image/providers/sirv'
+import * as hygraph from '#image/providers/hygraph'
 
 const emptyContext = {
   options: {
@@ -454,6 +455,17 @@ describe('Providers', () => {
     }
   })
 
+  it('hygraph', () => {
+    const providerOptions = {
+      baseURL: 'https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/',
+    }
+    for (const image of images) {
+      const [_src, modifiers] = image.args
+      const generated = hygraph.getImage('https://eu-central-1-shared-euc1-02.graphassets.com/cltsj3mii0pvd07vwb5cyh1ig/cltsrex89477t08unlckqx9ue', { modifiers, ...providerOptions }, emptyContext)
+      expect(generated).toMatchObject(image.hygraph)
+    }
+  })
+
   it('weserv', () => {
     const providerOptions = {
       baseURL: 'https://my-website.com/',