@wular/pnext 0.0.4 → 0.0.7
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 +22 -16
- package/bin/pnext +6 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +87 -22
- package/reference/config.md +40 -93
- package/reference/css.md +42 -33
- package/reference/dev.md +26 -33
- package/reference/env.md +18 -20
- package/reference/getting-started.md +132 -0
- package/reference/metadata.md +31 -46
- package/reference/navigation.md +65 -105
- package/reference/performance.md +21 -142
- package/reference/rendering.md +78 -75
- package/reference/routing.md +97 -107
- package/reference/typegen.md +27 -29
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +121 -114
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +52 -53
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +72 -64
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +94 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +802 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +32 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +2022 -1995
- package/src/{api → client}/router/types.ts +98 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1897
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +86 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2087 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +87 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +827 -815
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +954 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +428 -406
- package/src/styles.d.ts +9 -0
- package/src/types.ts +324 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/reference/overview.md +0 -35
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
|
@@ -9,31 +9,31 @@
|
|
|
9
9
|
// images.maximumDiskCacheSize (0 disables writes entirely).
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
|
|
12
|
-
import { createHash } from 'node:crypto'
|
|
13
|
-
import { promises as fs } from 'node:fs'
|
|
14
|
-
import path from 'node:path'
|
|
12
|
+
import { createHash } from 'node:crypto'
|
|
13
|
+
import { promises as fs } from 'node:fs'
|
|
14
|
+
import path from 'node:path'
|
|
15
15
|
|
|
16
|
-
export const IMAGE_CACHE_VERSION = 4
|
|
16
|
+
export const IMAGE_CACHE_VERSION = 4
|
|
17
17
|
|
|
18
18
|
export function getHash(items: (string | number | Buffer)[]): string {
|
|
19
|
-
const hash = createHash('sha256')
|
|
19
|
+
const hash = createHash('sha256')
|
|
20
20
|
for (const item of items) {
|
|
21
|
-
hash.update(typeof item === 'number' ? String(item) : item)
|
|
21
|
+
hash.update(typeof item === 'number' ? String(item) : item)
|
|
22
22
|
}
|
|
23
|
-
return hash.digest('base64url')
|
|
23
|
+
return hash.digest('base64url')
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export interface ImageCacheEntry {
|
|
27
|
-
buffer: Buffer
|
|
28
|
-
etag: string
|
|
29
|
-
upstreamEtag: string
|
|
30
|
-
extension: string
|
|
31
|
-
maxAge: number
|
|
32
|
-
expireAt: number
|
|
27
|
+
buffer: Buffer
|
|
28
|
+
etag: string
|
|
29
|
+
upstreamEtag: string
|
|
30
|
+
extension: string
|
|
31
|
+
maxAge: number
|
|
32
|
+
expireAt: number
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function imageCacheDir(root: string): string {
|
|
36
|
-
return path.join(root, '.next', 'cache', 'images')
|
|
36
|
+
return path.join(root, '.next', 'cache', 'images')
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export async function readCacheEntry(
|
|
@@ -41,13 +41,13 @@ export async function readCacheEntry(
|
|
|
41
41
|
cacheKey: string,
|
|
42
42
|
): Promise<ImageCacheEntry | undefined> {
|
|
43
43
|
try {
|
|
44
|
-
const dir = path.join(cacheDir, cacheKey)
|
|
45
|
-
const files = await fs.readdir(dir)
|
|
46
|
-
const file = files[0]
|
|
47
|
-
if (!file) return undefined
|
|
48
|
-
const [maxAgeSt, expireAtSt, etag, upstreamEtag, extension] = file.split('.', 5)
|
|
49
|
-
if (!etag || !upstreamEtag || !extension) return undefined
|
|
50
|
-
const buffer = await fs.readFile(path.join(dir, file))
|
|
44
|
+
const dir = path.join(cacheDir, cacheKey)
|
|
45
|
+
const files = await fs.readdir(dir)
|
|
46
|
+
const file = files[0]
|
|
47
|
+
if (!file) return undefined
|
|
48
|
+
const [maxAgeSt, expireAtSt, etag, upstreamEtag, extension] = file.split('.', 5)
|
|
49
|
+
if (!etag || !upstreamEtag || !extension) return undefined
|
|
50
|
+
const buffer = await fs.readFile(path.join(dir, file))
|
|
51
51
|
return {
|
|
52
52
|
buffer,
|
|
53
53
|
etag,
|
|
@@ -55,9 +55,9 @@ export async function readCacheEntry(
|
|
|
55
55
|
extension,
|
|
56
56
|
maxAge: Number(maxAgeSt),
|
|
57
57
|
expireAt: Number(expireAtSt),
|
|
58
|
-
}
|
|
58
|
+
}
|
|
59
59
|
} catch {
|
|
60
|
-
return undefined
|
|
60
|
+
return undefined
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -67,24 +67,24 @@ export async function writeCacheEntry(
|
|
|
67
67
|
entry: ImageCacheEntry,
|
|
68
68
|
maximumDiskCacheSize: number | undefined,
|
|
69
69
|
): Promise<void> {
|
|
70
|
-
if (maximumDiskCacheSize === 0) return
|
|
70
|
+
if (maximumDiskCacheSize === 0) return
|
|
71
71
|
if (maximumDiskCacheSize !== undefined && entry.buffer.byteLength > maximumDiskCacheSize) {
|
|
72
|
-
return
|
|
72
|
+
return
|
|
73
73
|
}
|
|
74
74
|
try {
|
|
75
|
-
const dir = path.join(cacheDir, cacheKey)
|
|
75
|
+
const dir = path.join(cacheDir, cacheKey)
|
|
76
76
|
const filename = path.join(
|
|
77
77
|
dir,
|
|
78
78
|
`${entry.maxAge}.${entry.expireAt}.${entry.etag}.${entry.upstreamEtag}.${entry.extension}`,
|
|
79
|
-
)
|
|
80
|
-
await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined)
|
|
81
|
-
await fs.mkdir(dir, { recursive: true })
|
|
82
|
-
await fs.writeFile(filename, entry.buffer)
|
|
79
|
+
)
|
|
80
|
+
await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined)
|
|
81
|
+
await fs.mkdir(dir, { recursive: true })
|
|
82
|
+
await fs.writeFile(filename, entry.buffer)
|
|
83
83
|
if (maximumDiskCacheSize !== undefined) {
|
|
84
|
-
await evictToBudget(cacheDir, cacheKey, maximumDiskCacheSize)
|
|
84
|
+
await evictToBudget(cacheDir, cacheKey, maximumDiskCacheSize)
|
|
85
85
|
}
|
|
86
86
|
} catch (err) {
|
|
87
|
-
console.error(`Failed to write image to cache ${cacheKey}`, err)
|
|
87
|
+
console.error(`Failed to write image to cache ${cacheKey}`, err)
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -95,25 +95,27 @@ async function evictToBudget(
|
|
|
95
95
|
keepKey: string,
|
|
96
96
|
maximumDiskCacheSize: number,
|
|
97
97
|
): Promise<void> {
|
|
98
|
-
const keys = await fs.readdir(cacheDir).catch(() => [] as string[])
|
|
99
|
-
const entries: { key: string; size: number; expireAt: number }[] = []
|
|
100
|
-
let total = 0
|
|
98
|
+
const keys = await fs.readdir(cacheDir).catch(() => [] as string[])
|
|
99
|
+
const entries: { key: string; size: number; expireAt: number }[] = []
|
|
100
|
+
let total = 0
|
|
101
101
|
for (const key of keys) {
|
|
102
|
-
const dir = path.join(cacheDir, key)
|
|
103
|
-
const files = await fs.readdir(dir).catch(() => [] as string[])
|
|
104
|
-
const file = files[0]
|
|
105
|
-
if (!file) continue
|
|
106
|
-
const stat = await fs.stat(path.join(dir, file)).catch(() => null)
|
|
107
|
-
if (!stat) continue
|
|
108
|
-
total += stat.size
|
|
109
|
-
entries.push({ key, size: stat.size, expireAt: Number(file.split('.', 2)[1]) || 0 })
|
|
102
|
+
const dir = path.join(cacheDir, key)
|
|
103
|
+
const files = await fs.readdir(dir).catch(() => [] as string[])
|
|
104
|
+
const file = files[0]
|
|
105
|
+
if (!file) continue
|
|
106
|
+
const stat = await fs.stat(path.join(dir, file)).catch(() => null)
|
|
107
|
+
if (!stat) continue
|
|
108
|
+
total += stat.size
|
|
109
|
+
entries.push({ key, size: stat.size, expireAt: Number(file.split('.', 2)[1]) || 0 })
|
|
110
110
|
}
|
|
111
|
-
if (total <= maximumDiskCacheSize) return
|
|
112
|
-
entries.sort((a, b) => a.expireAt - b.expireAt)
|
|
111
|
+
if (total <= maximumDiskCacheSize) return
|
|
112
|
+
entries.sort((a, b) => a.expireAt - b.expireAt)
|
|
113
113
|
for (const entry of entries) {
|
|
114
|
-
if (total <= maximumDiskCacheSize) break
|
|
115
|
-
if (entry.key === keepKey) continue
|
|
116
|
-
await fs
|
|
117
|
-
|
|
114
|
+
if (total <= maximumDiskCacheSize) break
|
|
115
|
+
if (entry.key === keepKey) continue
|
|
116
|
+
await fs
|
|
117
|
+
.rm(path.join(cacheDir, entry.key), { recursive: true, force: true })
|
|
118
|
+
.catch(() => undefined)
|
|
119
|
+
total -= entry.size
|
|
118
120
|
}
|
|
119
121
|
}
|
|
@@ -3,25 +3,25 @@
|
|
|
3
3
|
// serve-static tables so the optimizer classifies sources (bypass vs optimize vs reject) exactly like
|
|
4
4
|
// Next.
|
|
5
5
|
|
|
6
|
-
export const AVIF = 'image/avif'
|
|
7
|
-
export const WEBP = 'image/webp'
|
|
8
|
-
export const PNG = 'image/png'
|
|
9
|
-
export const JPEG = 'image/jpeg'
|
|
10
|
-
export const JXL = 'image/jxl'
|
|
11
|
-
export const JP2 = 'image/jp2'
|
|
12
|
-
export const HEIC = 'image/heic'
|
|
13
|
-
export const GIF = 'image/gif'
|
|
14
|
-
export const SVG = 'image/svg+xml'
|
|
15
|
-
export const ICO = 'image/x-icon'
|
|
16
|
-
export const ICNS = 'image/x-icns'
|
|
17
|
-
export const TIFF = 'image/tiff'
|
|
18
|
-
export const BMP = 'image/bmp'
|
|
19
|
-
export const PDF = 'application/pdf'
|
|
6
|
+
export const AVIF = 'image/avif'
|
|
7
|
+
export const WEBP = 'image/webp'
|
|
8
|
+
export const PNG = 'image/png'
|
|
9
|
+
export const JPEG = 'image/jpeg'
|
|
10
|
+
export const JXL = 'image/jxl'
|
|
11
|
+
export const JP2 = 'image/jp2'
|
|
12
|
+
export const HEIC = 'image/heic'
|
|
13
|
+
export const GIF = 'image/gif'
|
|
14
|
+
export const SVG = 'image/svg+xml'
|
|
15
|
+
export const ICO = 'image/x-icon'
|
|
16
|
+
export const ICNS = 'image/x-icns'
|
|
17
|
+
export const TIFF = 'image/tiff'
|
|
18
|
+
export const BMP = 'image/bmp'
|
|
19
|
+
export const PDF = 'application/pdf'
|
|
20
20
|
|
|
21
21
|
/** Animated variants of these are served as-is (never re-encoded). */
|
|
22
|
-
export const ANIMATABLE_TYPES = [WEBP, PNG, GIF]
|
|
22
|
+
export const ANIMATABLE_TYPES = [WEBP, PNG, GIF]
|
|
23
23
|
/** Types sharp never re-encodes — passthrough with the original bytes. */
|
|
24
|
-
export const BYPASS_TYPES = [SVG, ICO, ICNS, BMP, JXL, HEIC]
|
|
24
|
+
export const BYPASS_TYPES = [SVG, ICO, ICNS, BMP, JXL, HEIC]
|
|
25
25
|
|
|
26
26
|
const EXTENSION_BY_TYPE: Record<string, string> = {
|
|
27
27
|
[AVIF]: 'avif',
|
|
@@ -37,25 +37,25 @@ const EXTENSION_BY_TYPE: Record<string, string> = {
|
|
|
37
37
|
[ICNS]: 'icns',
|
|
38
38
|
[TIFF]: 'tiff',
|
|
39
39
|
[BMP]: 'bmp',
|
|
40
|
-
}
|
|
40
|
+
}
|
|
41
41
|
|
|
42
42
|
const TYPE_BY_EXTENSION: Record<string, string> = Object.fromEntries(
|
|
43
43
|
Object.entries(EXTENSION_BY_TYPE).map(([type, ext]) => [ext, type]),
|
|
44
|
-
)
|
|
44
|
+
)
|
|
45
45
|
|
|
46
46
|
/** File extension for a content type (Next's getExtension); undefined if unknown. */
|
|
47
47
|
export function extensionForType(contentType: string): string | undefined {
|
|
48
|
-
return EXTENSION_BY_TYPE[contentType]
|
|
48
|
+
return EXTENSION_BY_TYPE[contentType]
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/** Content type for a cache-file extension (Next's getContentType). */
|
|
52
52
|
export function typeForExtension(extension: string): string | undefined {
|
|
53
|
-
return TYPE_BY_EXTENSION[extension]
|
|
53
|
+
return TYPE_BY_EXTENSION[extension]
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function startsWithBytes(buffer: Buffer, bytes: number[]): boolean {
|
|
57
57
|
// A zero in the signature is a wildcard byte (Next's convention).
|
|
58
|
-
return bytes.every((b, i) => !b || buffer[i] === b)
|
|
58
|
+
return bytes.every((b, i) => !b || buffer[i] === b)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -64,72 +64,72 @@ function startsWithBytes(buffer: Buffer, bytes: number[]): boolean {
|
|
|
64
64
|
* unknown formats.
|
|
65
65
|
*/
|
|
66
66
|
export function detectContentType(buffer: Buffer): string | null {
|
|
67
|
-
if (buffer.byteLength === 0) return null
|
|
68
|
-
if ([0xff, 0xd8, 0xff].every((b, i) => buffer[i] === b)) return JPEG
|
|
67
|
+
if (buffer.byteLength === 0) return null
|
|
68
|
+
if ([0xff, 0xd8, 0xff].every((b, i) => buffer[i] === b)) return JPEG
|
|
69
69
|
if ([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].every((b, i) => buffer[i] === b)) {
|
|
70
|
-
return PNG
|
|
70
|
+
return PNG
|
|
71
71
|
}
|
|
72
|
-
if ([0x47, 0x49, 0x46, 0x38].every((b, i) => buffer[i] === b)) return GIF
|
|
72
|
+
if ([0x47, 0x49, 0x46, 0x38].every((b, i) => buffer[i] === b)) return GIF
|
|
73
73
|
if (startsWithBytes(buffer, [0x52, 0x49, 0x46, 0x46, 0, 0, 0, 0, 0x57, 0x45, 0x42, 0x50])) {
|
|
74
|
-
return WEBP
|
|
74
|
+
return WEBP
|
|
75
75
|
}
|
|
76
|
-
if ([0x3c, 0x3f, 0x78, 0x6d, 0x6c].every((b, i) => buffer[i] === b)) return SVG
|
|
77
|
-
if ([0x3c, 0x73, 0x76, 0x67].every((b, i) => buffer[i] === b)) return SVG
|
|
76
|
+
if ([0x3c, 0x3f, 0x78, 0x6d, 0x6c].every((b, i) => buffer[i] === b)) return SVG
|
|
77
|
+
if ([0x3c, 0x73, 0x76, 0x67].every((b, i) => buffer[i] === b)) return SVG
|
|
78
78
|
if (startsWithBytes(buffer, [0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66])) {
|
|
79
|
-
return AVIF
|
|
79
|
+
return AVIF
|
|
80
80
|
}
|
|
81
|
-
if ([0x00, 0x00, 0x01, 0x00].every((b, i) => buffer[i] === b)) return ICO
|
|
82
|
-
if ([0x69, 0x63, 0x6e, 0x73].every((b, i) => buffer[i] === b)) return ICNS
|
|
83
|
-
if ([0x49, 0x49, 0x2a, 0x00].every((b, i) => buffer[i] === b)) return TIFF
|
|
84
|
-
if ([0x4d, 0x4d, 0x00, 0x2a].every((b, i) => buffer[i] === b)) return TIFF
|
|
85
|
-
if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) return BMP
|
|
86
|
-
if ([0xff, 0x0a].every((b, i) => buffer[i] === b)) return JXL
|
|
81
|
+
if ([0x00, 0x00, 0x01, 0x00].every((b, i) => buffer[i] === b)) return ICO
|
|
82
|
+
if ([0x69, 0x63, 0x6e, 0x73].every((b, i) => buffer[i] === b)) return ICNS
|
|
83
|
+
if ([0x49, 0x49, 0x2a, 0x00].every((b, i) => buffer[i] === b)) return TIFF
|
|
84
|
+
if ([0x4d, 0x4d, 0x00, 0x2a].every((b, i) => buffer[i] === b)) return TIFF
|
|
85
|
+
if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) return BMP
|
|
86
|
+
if ([0xff, 0x0a].every((b, i) => buffer[i] === b)) return JXL
|
|
87
87
|
if (
|
|
88
88
|
[0x00, 0x00, 0x00, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every(
|
|
89
89
|
(b, i) => buffer[i] === b,
|
|
90
90
|
)
|
|
91
91
|
) {
|
|
92
|
-
return JXL
|
|
92
|
+
return JXL
|
|
93
93
|
}
|
|
94
94
|
if (startsWithBytes(buffer, [0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63])) {
|
|
95
|
-
return HEIC
|
|
95
|
+
return HEIC
|
|
96
96
|
}
|
|
97
|
-
if ([0x25, 0x50, 0x44, 0x46, 0x2d].every((b, i) => buffer[i] === b)) return PDF
|
|
97
|
+
if ([0x25, 0x50, 0x44, 0x46, 0x2d].every((b, i) => buffer[i] === b)) return PDF
|
|
98
98
|
if (
|
|
99
99
|
[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every(
|
|
100
100
|
(b, i) => buffer[i] === b,
|
|
101
101
|
)
|
|
102
102
|
) {
|
|
103
|
-
return JP2
|
|
103
|
+
return JP2
|
|
104
104
|
}
|
|
105
105
|
// SVG documents may start with whitespace/comments/doctype before <svg.
|
|
106
|
-
const head = buffer.toString('utf8', 0, Math.min(buffer.length, 512)).trimStart()
|
|
107
|
-
if (/^(<\?xml|<!doctype svg|<svg)/i.test(head)) return SVG
|
|
108
|
-
return null
|
|
106
|
+
const head = buffer.toString('utf8', 0, Math.min(buffer.length, 512)).trimStart()
|
|
107
|
+
if (/^(<\?xml|<!doctype svg|<svg)/i.test(head)) return SVG
|
|
108
|
+
return null
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/** True when a gif/apng/webp buffer contains multiple frames (Next's is-animated). */
|
|
112
112
|
export function isAnimated(buffer: Buffer): boolean {
|
|
113
113
|
// GIF: more than one Graphics Control Extension block (0x21 0xF9 0x04).
|
|
114
114
|
if (buffer.length > 6 && buffer.toString('ascii', 0, 3) === 'GIF') {
|
|
115
|
-
let frames = 0
|
|
115
|
+
let frames = 0
|
|
116
116
|
for (let i = 0; i < buffer.length - 2; i++) {
|
|
117
117
|
if (buffer[i] === 0x21 && buffer[i + 1] === 0xf9 && buffer[i + 2] === 0x04) {
|
|
118
|
-
frames
|
|
119
|
-
if (frames > 1) return true
|
|
118
|
+
frames++
|
|
119
|
+
if (frames > 1) return true
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
return false
|
|
122
|
+
return false
|
|
123
123
|
}
|
|
124
124
|
// APNG: an acTL chunk appearing before the first IDAT chunk.
|
|
125
125
|
if (
|
|
126
126
|
buffer.length > 8 &&
|
|
127
127
|
[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].every((b, i) => buffer[i] === b)
|
|
128
128
|
) {
|
|
129
|
-
const actl = buffer.indexOf('acTL')
|
|
130
|
-
if (actl === -1) return false
|
|
131
|
-
const idat = buffer.indexOf('IDAT')
|
|
132
|
-
return idat === -1 || actl < idat
|
|
129
|
+
const actl = buffer.indexOf('acTL')
|
|
130
|
+
if (actl === -1) return false
|
|
131
|
+
const idat = buffer.indexOf('IDAT')
|
|
132
|
+
return idat === -1 || actl < idat
|
|
133
133
|
}
|
|
134
134
|
// WebP: an ANIM chunk inside a VP8X container.
|
|
135
135
|
if (
|
|
@@ -137,7 +137,7 @@ export function isAnimated(buffer: Buffer): boolean {
|
|
|
137
137
|
buffer.toString('ascii', 0, 4) === 'RIFF' &&
|
|
138
138
|
buffer.toString('ascii', 8, 12) === 'WEBP'
|
|
139
139
|
) {
|
|
140
|
-
return buffer.includes('ANIM')
|
|
140
|
+
return buffer.includes('ANIM')
|
|
141
141
|
}
|
|
142
|
-
return false
|
|
142
|
+
return false
|
|
143
143
|
}
|