diff --git a/package.json b/package.json index 9dcd07c87..ffe94e188 100755 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "eslint": "9.39.2", "happy-dom": "^20.3.3", "installed-check": "^9.3.0", - "ipx": "^3.1.1", + "ipx": "^4.0.0-alpha.1", "jiti": "2.6.1", "knip": "^5.82.1", "nitropack": "^2.13.1", @@ -89,7 +89,7 @@ "vue-tsc": "^3.2.2" }, "optionalDependencies": { - "ipx": "^3.1.1" + "ipx": "^4.0.0-alpha.1" }, "packageManager": "pnpm@10.28.1", "resolutions": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d3f5b56ca..91933ea4e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,8 +134,8 @@ importers: version: 3.2.2(typescript@5.9.3) optionalDependencies: ipx: - specifier: ^3.1.1 - version: 3.1.1(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1) + specifier: ^4.0.0-alpha.1 + version: 4.0.0-alpha.1(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1)) docs: dependencies: @@ -153,7 +153,7 @@ importers: version: 12.6.2 docus: specifier: ^5.4.4 - version: 5.4.4(80147e075c6f2667a96e35455a68fcf7) + version: 5.4.4(cd0f9271b0f2fe38bb201317f4139068) tailwindcss: specifier: ^4.1.18 version: 4.1.18 @@ -753,9 +753,6 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@fastify/accept-negotiator@2.0.1': - resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==} - '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} @@ -3794,9 +3791,6 @@ packages: engines: {node: '>=4'} hasBin: true - cssfilter@0.0.10: - resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} - cssnano-preset-default@7.0.10: resolution: {integrity: sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA==} engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} @@ -4609,8 +4603,8 @@ packages: h3@1.15.5: resolution: {integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==} - h3@2.0.1-rc.8: - resolution: {integrity: sha512-IIMQG7qnXx1Ls75suuMHH4xtcvTFxsUguDIZB+dgdYr1RftLj59FkeWF1dOr+jnejDs8Eo+ZKV1CMqogFeqGRQ==} + h3@2.0.1-rc.11: + resolution: {integrity: sha512-2myzjCqy32c1As9TjZW9fNZXtLqNedjFSrdFy2AjFBQQ3LzrnGoDdFDYfC0tV2e4vcyfJ2Sfo/F6NQhO2Ly/Mw==} engines: {node: '>=20.11.1'} peerDependencies: crossws: ^0.4.1 @@ -4824,9 +4818,14 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - ipx@3.1.1: - resolution: {integrity: sha512-7Xnt54Dco7uYkfdAw0r2vCly3z0rSaVhEXMzPvl3FndsTVm5p26j+PO+gyinkYmcsEUvX2Rh7OGK7KzYWRu6BA==} + ipx@4.0.0-alpha.1: + resolution: {integrity: sha512-naIX/3xFfAOy5Wz2Z/UoQnpMVWGT0eblLSkHj3plcJsEuW040oiX/HqFwK1YygWUoROqSgFZkB6wTLra+GpwCQ==} hasBin: true + peerDependencies: + unstorage: '*' + peerDependenciesMeta: + unstorage: + optional: true iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -6682,8 +6681,8 @@ packages: resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} engines: {node: '>=12'} - srvx@0.10.0: - resolution: {integrity: sha512-NqIsR+wQCfkvvwczBh8J8uM4wTZx41K2lLSEp/3oMp917ODVVMtW5Me4epCmQ3gH8D+0b+/t4xxkUKutyhimTA==} + srvx@0.10.1: + resolution: {integrity: sha512-A//xtfak4eESMWWydSRFUVvCTQbSwivnGCEf8YGPe2eHU0+Z6znfUTCPF0a7oV3sObSOcrXHlL6Bs9vVctfXdg==} engines: {node: '>=20.16.0'} hasBin: true @@ -7582,11 +7581,6 @@ packages: resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} - xss@1.0.15: - resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==} - engines: {node: '>= 0.10.0'} - hasBin: true - y-protocols@1.0.7: resolution: {integrity: sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} @@ -8161,9 +8155,6 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@fastify/accept-negotiator@2.0.1': - optional: true - '@fastify/busboy@2.1.1': {} '@fingerprintjs/botd@2.0.0': {} @@ -8988,7 +8979,7 @@ snapshots: fake-indexeddb: 6.2.5 get-port-please: 3.2.0 h3: 1.15.5 - h3-next: h3@2.0.1-rc.8 + h3-next: h3@2.0.1-rc.11 local-pkg: 1.1.2 magic-string: 0.30.21 node-fetch-native: 1.6.7 @@ -9328,13 +9319,13 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxtjs/robots@5.6.7(h3@1.15.5)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3))(zod@4.3.5)': + '@nuxtjs/robots@5.6.7(h3@2.0.1-rc.11)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3))(zod@4.3.5)': dependencies: '@fingerprintjs/botd': 2.0.0 '@nuxt/kit': 4.2.2(magicast@0.5.1) consola: 3.4.2 defu: 6.1.4 - nuxt-site-config: 3.2.14(h3@1.15.5)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) + nuxt-site-config: 3.2.14(h3@2.0.1-rc.11)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) pathe: 2.0.3 pkg-types: 2.3.0 sirv: 3.0.2 @@ -11538,9 +11529,6 @@ snapshots: cssesc@3.0.0: {} - cssfilter@0.0.10: - optional: true - cssnano-preset-default@7.0.10(postcss@8.5.6): dependencies: browserslist: 4.28.1 @@ -11674,7 +11662,7 @@ snapshots: diff@8.0.2: {} - docus@5.4.4(80147e075c6f2667a96e35455a68fcf7): + docus@5.4.4(cd0f9271b0f2fe38bb201317f4139068): dependencies: '@iconify-json/lucide': 1.2.86 '@iconify-json/simple-icons': 1.2.67 @@ -11686,7 +11674,7 @@ snapshots: '@nuxtjs/i18n': 10.2.1(@vue/compiler-dom@3.5.27)(db0@0.3.4(better-sqlite3@12.6.2))(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.1)(magicast@0.5.1)(rollup@4.55.1)(vue@3.5.27(typescript@5.9.3)) '@nuxtjs/mcp-toolkit': 0.6.2(hono@4.11.1)(magicast@0.5.1)(zod@4.3.5) '@nuxtjs/mdc': 0.20.0(magicast@0.5.1) - '@nuxtjs/robots': 5.6.7(h3@1.15.5)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3))(zod@4.3.5) + '@nuxtjs/robots': 5.6.7(h3@2.0.1-rc.11)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3))(zod@4.3.5) '@vueuse/core': 14.1.0(vue@3.5.27(typescript@5.9.3)) better-sqlite3: 12.6.2 defu: 6.1.4 @@ -11696,7 +11684,7 @@ snapshots: motion-v: 1.9.0(@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3)))(vue@3.5.27(typescript@5.9.3)) nuxt: 4.2.2(@parcel/watcher@2.5.1)(@types/node@24.10.9)(@vue/compiler-sfc@3.5.27)(better-sqlite3@12.6.2)(cac@6.7.14)(db0@0.3.4(better-sqlite3@12.6.2))(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.1)(lightningcss@1.30.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.55.1)(terser@5.44.1)(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue-tsc@3.2.2(typescript@5.9.3))(yaml@2.8.2) nuxt-llms: 0.2.0(magicast@0.5.1) - nuxt-og-image: 5.1.13(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(h3@1.15.5)(magicast@0.5.1)(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1))(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + nuxt-og-image: 5.1.13(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(h3@2.0.1-rc.11)(magicast@0.5.1)(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1))(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) pkg-types: 2.3.0 scule: 1.3.0 tailwindcss: 4.1.18 @@ -12572,10 +12560,10 @@ snapshots: ufo: 1.6.3 uncrypto: 0.1.3 - h3@2.0.1-rc.8: + h3@2.0.1-rc.11: dependencies: rou3: 0.7.12 - srvx: 0.10.0 + srvx: 0.10.1 happy-dom@20.3.3: dependencies: @@ -12868,44 +12856,13 @@ snapshots: ipaddr.js@1.9.1: {} - ipx@3.1.1(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1): + ipx@4.0.0-alpha.1(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1)): dependencies: - '@fastify/accept-negotiator': 2.0.1 - citty: 0.1.6 - consola: 3.4.2 - defu: 6.1.4 - destr: 2.0.5 - etag: 1.8.1 - h3: 1.15.5 - image-meta: 0.2.2 - listhen: 1.9.0 - ofetch: 1.5.1 pathe: 2.0.3 sharp: 0.34.5 - svgo: 4.0.0 - ufo: 1.6.3 + srvx: 0.9.8 + optionalDependencies: unstorage: 1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1) - xss: 1.0.15 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - db0 - - idb-keyval - - ioredis - - uploadthing optional: true iron-webcrypto@1.2.1: {} @@ -13978,7 +13935,7 @@ snapshots: transitivePeerDependencies: - magicast - nuxt-og-image@5.1.13(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(h3@1.15.5)(magicast@0.5.1)(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1))(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)): + nuxt-og-image@5.1.13(@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3)))(h3@2.0.1-rc.11)(magicast@0.5.1)(unstorage@1.17.4(db0@0.3.4(better-sqlite3@12.6.2))(ioredis@5.9.1))(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)): dependencies: '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.0(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@nuxt/kit': 4.2.2(magicast@0.5.1) @@ -13994,7 +13951,7 @@ snapshots: image-size: 2.0.2 magic-string: 0.30.21 mocked-exports: 0.1.1 - nuxt-site-config: 3.2.14(h3@1.15.5)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) + nuxt-site-config: 3.2.14(h3@2.0.1-rc.11)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) nypm: 0.6.2 ofetch: 1.5.1 ohash: 2.0.11 @@ -14030,10 +13987,10 @@ snapshots: - magicast - vue - nuxt-site-config@3.2.14(h3@1.15.5)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)): + nuxt-site-config@3.2.14(h3@2.0.1-rc.11)(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)): dependencies: '@nuxt/kit': 4.2.2(magicast@0.5.1) - h3: 1.15.5 + h3: 2.0.1-rc.11 nuxt-site-config-kit: 3.2.14(magicast@0.5.1)(vue@3.5.27(typescript@5.9.3)) pathe: 2.0.3 pkg-types: 2.3.0 @@ -15455,7 +15412,7 @@ snapshots: split-on-first@3.0.0: {} - srvx@0.10.0: {} + srvx@0.10.1: {} srvx@0.9.8: {} @@ -16396,12 +16353,6 @@ snapshots: xmlhttprequest-ssl@2.1.2: {} - xss@1.0.15: - dependencies: - commander: 2.20.3 - cssfilter: 0.0.10 - optional: true - y-protocols@1.0.7(yjs@13.6.28): dependencies: lib0: 0.2.117 diff --git a/src/runtime/server/routes/_ipx.ts b/src/runtime/server/routes/_ipx.ts index 0b8cb04c4..437e3b738 100644 --- a/src/runtime/server/routes/_ipx.ts +++ b/src/runtime/server/routes/_ipx.ts @@ -1,8 +1,8 @@ import { fileURLToPath } from 'node:url' -import { createIPX, createIPXH3Handler, ipxFSStorage, ipxHttpStorage } from 'ipx' +import { createIPX, createIPXFetchHandler, ipxFSStorage, ipxHttpStorage } from 'ipx' import type { IPXOptions } from 'ipx' -import { lazyEventHandler, useBase } from 'h3' +import { lazyEventHandler, defineEventHandler, getRequestURL, sendWebResponse } from 'h3' import { isAbsolute } from 'pathe' import type { NitroRuntimeConfig } from 'nitropack' @@ -27,7 +27,29 @@ export default lazyEventHandler(() => { } const ipx = createIPX(ipxOptions) - - const ipxHandler = createIPXH3Handler(ipx) - return useBase(opts.baseURL, ipxHandler) + const _handler = createIPXFetchHandler(ipx) + + return defineEventHandler(async (event) => { + // Get the path after the base URL (e.g., /_ipx) + const url = getRequestURL(event) + + // Strip the base URL prefix from the pathname + const baseURL = opts.baseURL || '/_ipx' + let pathname = url.pathname + if (pathname.startsWith(baseURL)) { + pathname = pathname.slice(baseURL.length) || '/' + } + + // Create a new URL with the stripped pathname for IPX + const ipxURL = new URL(pathname + url.search, url.origin) + + // Create a request with the modified URL + const request = new Request(ipxURL, { + method: event.method, + headers: event.headers, + }) + + const response = await _handler(request) + return sendWebResponse(event, response) + }) })