@wular/pnext 0.0.1
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 +153 -0
- package/bin/pnext +67 -0
- package/config/lint/base.js +48 -0
- package/config/ts/base.json +26 -0
- package/config/ts/react.json +13 -0
- package/package.json +70 -0
- package/reference/compat.md +63 -0
- package/reference/config.md +120 -0
- package/reference/css.md +58 -0
- package/reference/dev.md +69 -0
- package/reference/env.md +40 -0
- package/reference/metadata.md +86 -0
- package/reference/navigation.md +149 -0
- package/reference/overview.md +35 -0
- package/reference/performance.md +97 -0
- package/reference/rendering.md +127 -0
- package/reference/routing.md +167 -0
- package/reference/typegen.md +64 -0
- package/src/api/cache.ts +80 -0
- package/src/api/client-cache.ts +9 -0
- package/src/api/client-navigation.ts +279 -0
- package/src/api/dynamic.tsx +102 -0
- package/src/api/link.tsx +119 -0
- package/src/api/navigation.ts +198 -0
- package/src/api/router/events.ts +53 -0
- package/src/api/router/history.ts +70 -0
- package/src/api/router/hub.ts +194 -0
- package/src/api/router/policies.ts +107 -0
- package/src/api/router/runtime.ts +5238 -0
- package/src/api/router/types.ts +299 -0
- package/src/api/router.ts +167 -0
- package/src/api/server.ts +323 -0
- package/src/api/suspense.ts +16 -0
- package/src/cache/context.ts +61 -0
- package/src/cli/adapters/vercel-warm.ts +375 -0
- package/src/cli/adapters/vercel.ts +1310 -0
- package/src/cli/analyze-print.ts +181 -0
- package/src/cli/analyze.ts +328 -0
- package/src/cli/boot-trace.ts +29 -0
- package/src/cli/build.ts +3114 -0
- package/src/cli/dev.ts +276 -0
- package/src/cli/index.ts +196 -0
- package/src/cli/named-bin.ts +119 -0
- package/src/cli/serve-ui.ts +160 -0
- package/src/cli/start.ts +1425 -0
- package/src/client/build.ts +2136 -0
- package/src/client/chunk-fold.ts +526 -0
- package/src/client/entry.ts +1525 -0
- package/src/client/paths.ts +22 -0
- package/src/client/prebuilt.ts +621 -0
- package/src/client/profile.ts +75 -0
- package/src/client/react-compiler.ts +94 -0
- package/src/client/reference-stub.ts +145 -0
- package/src/client/reference.ts +47 -0
- package/src/compat/actions/action-client.ts +531 -0
- package/src/compat/actions/action-dispatch.ts +676 -0
- package/src/compat/actions/action-router.ts +40 -0
- package/src/compat/actions/action-shared.ts +95 -0
- package/src/compat/actions/client-plugin.ts +135 -0
- package/src/compat/actions/client-stub.ts +65 -0
- package/src/compat/actions/config.ts +164 -0
- package/src/compat/actions/detect.ts +208 -0
- package/src/compat/actions/discovery.ts +244 -0
- package/src/compat/actions/early-submit.ts +40 -0
- package/src/compat/actions/endpoint.ts +602 -0
- package/src/compat/actions/flight.ts +52 -0
- package/src/compat/actions/form-state.ts +73 -0
- package/src/compat/actions/hoist.ts +485 -0
- package/src/compat/actions/ids.ts +39 -0
- package/src/compat/actions/index.ts +41 -0
- package/src/compat/actions/instances.ts +144 -0
- package/src/compat/actions/origin.ts +109 -0
- package/src/compat/actions/protocol.ts +125 -0
- package/src/compat/actions/registry.ts +74 -0
- package/src/compat/actions/rewrite.ts +282 -0
- package/src/compat/actions/serve.ts +414 -0
- package/src/compat/actions/server-tag.ts +21 -0
- package/src/compat/actions/unrecognized-error.ts +30 -0
- package/src/compat/adapter/build-complete.ts +257 -0
- package/src/compat/bundler/bun-externals.ts +53 -0
- package/src/compat/bundler/cjs-exports.ts +542 -0
- package/src/compat/bundler/config.ts +363 -0
- package/src/compat/bundler/externals.ts +34 -0
- package/src/compat/bundler/import-meta-url.ts +60 -0
- package/src/compat/bundler/modularize-imports.ts +119 -0
- package/src/compat/bundler/new-url-asset.ts +87 -0
- package/src/compat/bundler/optimize-package-imports.ts +273 -0
- package/src/compat/bundler/polyfill.ts +88 -0
- package/src/compat/bundler/react-compiler.ts +61 -0
- package/src/compat/bundler/react-profiler.tsx +25 -0
- package/src/compat/bundler/relay-transform.ts +116 -0
- package/src/compat/bundler/require-context.ts +281 -0
- package/src/compat/bundler/resolve-extensions.ts +75 -0
- package/src/compat/bundler/source-cache.ts +61 -0
- package/src/compat/bundler/static-imports.ts +25 -0
- package/src/compat/bundler/symlink-imports.ts +119 -0
- package/src/compat/bundler/tsconfig-paths.ts +50 -0
- package/src/compat/bundler/wasm.ts +153 -0
- package/src/compat/bundler/webpack-loaders.ts +685 -0
- package/src/compat/bundler/worker.ts +278 -0
- package/src/compat/cache/build-flags.ts +81 -0
- package/src/compat/cache/build-prerender-errors.ts +163 -0
- package/src/compat/cache/custom-handler.ts +159 -0
- package/src/compat/cache/fetch-patch.ts +745 -0
- package/src/compat/cache/handler.ts +100 -0
- package/src/compat/cache/modern-handler.ts +275 -0
- package/src/compat/cache/resume-data-cache.ts +143 -0
- package/src/compat/cache/revalidate.ts +759 -0
- package/src/compat/cache/runtime-error.ts +124 -0
- package/src/compat/cache/use-cache-transform.ts +961 -0
- package/src/compat/cache/use-cache.ts +1695 -0
- package/src/compat/cache-control.ts +269 -0
- package/src/compat/client/base-path.ts +64 -0
- package/src/compat/client/css-order.ts +36 -0
- package/src/compat/client/errors/control-flow.ts +92 -0
- package/src/compat/client/errors/error-boundary.ts +222 -0
- package/src/compat/client/errors/global-error.ts +238 -0
- package/src/compat/client/errors/install.ts +217 -0
- package/src/compat/client/errors/lazy.ts +53 -0
- package/src/compat/client/errors/primitive-throw.ts +126 -0
- package/src/compat/client/errors/soft-refresh.ts +14 -0
- package/src/compat/client/link-status.ts +86 -0
- package/src/compat/client/nav-compat-runtime.ts +57 -0
- package/src/compat/client/nav-compat.ts +42 -0
- package/src/compat/client/navigation-scroll.ts +154 -0
- package/src/compat/client/optimistic-routing.ts +206 -0
- package/src/compat/client/prefetch-cache.ts +111 -0
- package/src/compat/client/route-announcer.ts +72 -0
- package/src/compat/client/segment-cache-policy.ts +159 -0
- package/src/compat/client/segment-cache.ts +1077 -0
- package/src/compat/client/segment-prefetch.ts +375 -0
- package/src/compat/client/trailing-slash.ts +24 -0
- package/src/compat/css/chunking.ts +254 -0
- package/src/compat/css/inline-css.ts +73 -0
- package/src/compat/css/lightningcss.ts +90 -0
- package/src/compat/css/modules.ts +373 -0
- package/src/compat/css/nonce.ts +30 -0
- package/src/compat/css/sass-plugin.ts +65 -0
- package/src/compat/css/sass.ts +392 -0
- package/src/compat/css/styled-jsx-runtime.ts +80 -0
- package/src/compat/css/styled-jsx.ts +49 -0
- package/src/compat/edge-runtime.ts +71 -0
- package/src/compat/export/client.ts +112 -0
- package/src/compat/export/index.ts +272 -0
- package/src/compat/export/standalone.ts +207 -0
- package/src/compat/image-optimizer/cache.ts +119 -0
- package/src/compat/image-optimizer/detect.ts +143 -0
- package/src/compat/image-optimizer/index.ts +601 -0
- package/src/compat/image-optimizer/source.ts +243 -0
- package/src/compat/index.ts +458 -0
- package/src/compat/lifecycle/after-scope.ts +86 -0
- package/src/compat/lifecycle/after.ts +173 -0
- package/src/compat/lifecycle/error-funnel.ts +306 -0
- package/src/compat/lifecycle/error-serialize.ts +87 -0
- package/src/compat/lifecycle/error-ui.ts +167 -0
- package/src/compat/lifecycle/instrumentation-client.ts +138 -0
- package/src/compat/lifecycle/instrumentation.ts +277 -0
- package/src/compat/lifecycle/node-console.ts +19 -0
- package/src/compat/lifecycle/testmode.ts +263 -0
- package/src/compat/mdx/compile.ts +219 -0
- package/src/compat/mdx/next-mdx-stub.ts +46 -0
- package/src/compat/mdx/plugin.ts +37 -0
- package/src/compat/metadata-route-artifacts.ts +458 -0
- package/src/compat/metadata.ts +295 -0
- package/src/compat/middleware/manifest.ts +210 -0
- package/src/compat/misc/action-return.ts +173 -0
- package/src/compat/next/cache.ts +211 -0
- package/src/compat/next/canonical-url.ts +35 -0
- package/src/compat/next/client-cache.ts +57 -0
- package/src/compat/next/client-navigation.ts +313 -0
- package/src/compat/next/client-only.ts +3 -0
- package/src/compat/next/client-script.tsx +215 -0
- package/src/compat/next/client-server.ts +39 -0
- package/src/compat/next/config-loader.ts +569 -0
- package/src/compat/next/config.ts +29 -0
- package/src/compat/next/constants.cjs +6 -0
- package/src/compat/next/constants.ts +6 -0
- package/src/compat/next/custom-server.ts +236 -0
- package/src/compat/next/dist/client/components/app-router-headers.ts +32 -0
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +38 -0
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -0
- package/src/compat/next/dynamic.tsx +46 -0
- package/src/compat/next/error.tsx +148 -0
- package/src/compat/next/font/cache.ts +171 -0
- package/src/compat/next/font/google.ts +2 -0
- package/src/compat/next/font/index.ts +8 -0
- package/src/compat/next/font/local.ts +5 -0
- package/src/compat/next/font/runtime-client.ts +71 -0
- package/src/compat/next/font/runtime.ts +974 -0
- package/src/compat/next/font/shared.ts +281 -0
- package/src/compat/next/form.tsx +156 -0
- package/src/compat/next/head.tsx +10 -0
- package/src/compat/next/headers.ts +247 -0
- package/src/compat/next/image/config.ts +196 -0
- package/src/compat/next/image/optimizer.ts +96 -0
- package/src/compat/next/image/patterns.ts +103 -0
- package/src/compat/next/image/shared.ts +141 -0
- package/src/compat/next/image/static-metadata.ts +283 -0
- package/src/compat/next/image/validate.ts +269 -0
- package/src/compat/next/image-client.tsx +215 -0
- package/src/compat/next/image-props.ts +575 -0
- package/src/compat/next/image-usage.ts +102 -0
- package/src/compat/next/image.tsx +56 -0
- package/src/compat/next/index.ts +1 -0
- package/src/compat/next/legacy-image.tsx +97 -0
- package/src/compat/next/link-usage.ts +29 -0
- package/src/compat/next/link-validation-transform.ts +200 -0
- package/src/compat/next/link.tsx +466 -0
- package/src/compat/next/navigation.cjs +21 -0
- package/src/compat/next/navigation.ts +188 -0
- package/src/compat/next/offline.ts +51 -0
- package/src/compat/next/og.ts +324 -0
- package/src/compat/next/optimistic-route-state.ts +188 -0
- package/src/compat/next/preferred-region.ts +39 -0
- package/src/compat/next/redirects.ts +131 -0
- package/src/compat/next/resource-hints.ts +136 -0
- package/src/compat/next/rewrites.ts +350 -0
- package/src/compat/next/root-params.ts +142 -0
- package/src/compat/next/router.cjs +49 -0
- package/src/compat/next/router.ts +143 -0
- package/src/compat/next/script.tsx +355 -0
- package/src/compat/next/server-only.ts +3 -0
- package/src/compat/next/server.ts +28 -0
- package/src/compat/next/svgr.ts +58 -0
- package/src/compat/next/telemetry.ts +77 -0
- package/src/compat/next/user-agent.ts +100 -0
- package/src/compat/next/web-vitals.ts +56 -0
- package/src/compat/otel/api.ts +95 -0
- package/src/compat/otel/client-trace-metadata.ts +71 -0
- package/src/compat/otel/fetch-span.ts +77 -0
- package/src/compat/otel/tracer.ts +944 -0
- package/src/compat/pages/client-plugin.ts +108 -0
- package/src/compat/pages/index.ts +527 -0
- package/src/compat/pages/router-state.ts +94 -0
- package/src/compat/ppr/io.ts +38 -0
- package/src/compat/ppr/missing-root-params.ts +105 -0
- package/src/compat/ppr/root-params-scan.ts +164 -0
- package/src/compat/ppr/root-params-transform.ts +75 -0
- package/src/compat/ppr/root-params.ts +129 -0
- package/src/compat/ppr/segment-config-incompat.ts +34 -0
- package/src/compat/protocol.ts +202 -0
- package/src/compat/react/client.ts +59 -0
- package/src/compat/react/compiler-runtime.ts +60 -0
- package/src/compat/react/dom-client.ts +115 -0
- package/src/compat/react/dom-react-server.ts +20 -0
- package/src/compat/react/dom-server.ts +40 -0
- package/src/compat/react/dom.ts +154 -0
- package/src/compat/react/preact.ts +522 -0
- package/src/compat/react/react-server.ts +84 -0
- package/src/compat/react/router-shim.ts +26 -0
- package/src/compat/react/server-component-use.ts +48 -0
- package/src/compat/react/server-inserted-html.ts +87 -0
- package/src/compat/react/server.ts +156 -0
- package/src/compat/react/view-transition.ts +60 -0
- package/src/compat/register/actions.ts +875 -0
- package/src/compat/register/boot.ts +141 -0
- package/src/compat/register/build-tier.ts +11 -0
- package/src/compat/register/build.ts +182 -0
- package/src/compat/register/bundler.ts +587 -0
- package/src/compat/register/cache.ts +85 -0
- package/src/compat/register/client-errors.ts +18 -0
- package/src/compat/register/config.ts +17 -0
- package/src/compat/register/css-extras.ts +120 -0
- package/src/compat/register/edge-runtime.ts +6 -0
- package/src/compat/register/errors.ts +46 -0
- package/src/compat/register/export.ts +23 -0
- package/src/compat/register/font.ts +36 -0
- package/src/compat/register/hooks.ts +34 -0
- package/src/compat/register/image.ts +133 -0
- package/src/compat/register/index.ts +111 -0
- package/src/compat/register/instrumentation-client.ts +35 -0
- package/src/compat/register/lifecycle.ts +86 -0
- package/src/compat/register/mdx.ts +48 -0
- package/src/compat/register/middleware.ts +36 -0
- package/src/compat/register/misc.ts +44 -0
- package/src/compat/register/otel.ts +288 -0
- package/src/compat/register/pages-api.ts +473 -0
- package/src/compat/register/ppr.ts +56 -0
- package/src/compat/register/protocol.ts +57 -0
- package/src/compat/register/proxy.ts +127 -0
- package/src/compat/register/render.ts +268 -0
- package/src/compat/register/routing.ts +410 -0
- package/src/compat/register/segment.ts +1903 -0
- package/src/compat/register/static-image.ts +21 -0
- package/src/compat/register/typed-routes.ts +35 -0
- package/src/compat/register/usecache.ts +131 -0
- package/src/compat/register/validation.ts +56 -0
- package/src/compat/segment/loading-boundary.ts +113 -0
- package/src/compat/segment/page-slot.ts +200 -0
- package/src/compat/segment/tree.ts +481 -0
- package/src/compat/segment/vary-key.ts +102 -0
- package/src/compat/segment/vary-params.ts +551 -0
- package/src/compat/static-params.ts +33 -0
- package/src/compat/tsconfig-defaults.ts +301 -0
- package/src/compat/typecheck/index.ts +1481 -0
- package/src/compat/typecheck/worker.ts +26 -0
- package/src/compat/typed-routes/index.ts +92 -0
- package/src/compat/typed-routes/manifest.ts +356 -0
- package/src/compat/typed-routes/typegen.ts +566 -0
- package/src/compat/validation/errors.ts +159 -0
- package/src/compat/validation/index.ts +1770 -0
- package/src/compat/validation/prerender-diagnostics.ts +1508 -0
- package/src/compat-bootstrap.ts +67 -0
- package/src/config.ts +218 -0
- package/src/css/build.ts +697 -0
- package/src/css/index.ts +2 -0
- package/src/css/postcss.ts +236 -0
- package/src/css/worker.ts +34 -0
- package/src/dev/client-actions.ts +35 -0
- package/src/dev/client-chunk-store.ts +92 -0
- package/src/dev/client-key-cache.ts +178 -0
- package/src/dev/global-css-cache.ts +212 -0
- package/src/dev/imports.ts +2430 -0
- package/src/dev/module-cache.ts +721 -0
- package/src/dev/module-generations.ts +38 -0
- package/src/dev/module-transform.ts +188 -0
- package/src/dev/node-module-bundle-cache.ts +63 -0
- package/src/dev/restart-cache.ts +10 -0
- package/src/dev/route-bundle-key-cache.ts +154 -0
- package/src/dev/route-facts-cache.ts +223 -0
- package/src/dev/server.ts +1710 -0
- package/src/dynamic/source.ts +307 -0
- package/src/dynamic/tree-shake.ts +262 -0
- package/src/env.ts +92 -0
- package/src/extensions.ts +1898 -0
- package/src/index.ts +34 -0
- package/src/internal.ts +43 -0
- package/src/islands/boundary-error.ts +8 -0
- package/src/islands/static-children.ts +37 -0
- package/src/islands/static-slots.ts +106 -0
- package/src/ppr-postpone.ts +24 -0
- package/src/ppr.ts +784 -0
- package/src/proxy.ts +752 -0
- package/src/render/hooks.ts +384 -0
- package/src/render/index.ts +1 -0
- package/src/render/island-context.ts +47 -0
- package/src/render/metadata.ts +857 -0
- package/src/render/renderer.ts +7391 -0
- package/src/render/resource-hints.ts +44 -0
- package/src/render/slots.tsx +679 -0
- package/src/request/context.ts +396 -0
- package/src/resolve/engine.ts +219 -0
- package/src/resolve/imports.ts +1104 -0
- package/src/resolve/scan-facts.ts +474 -0
- package/src/resolve/source-text.ts +86 -0
- package/src/routing/forwarded.ts +41 -0
- package/src/routing/handler.ts +271 -0
- package/src/routing/href.ts +203 -0
- package/src/routing/metadata.ts +1018 -0
- package/src/routing/request-runtime.ts +43 -0
- package/src/routing/routes.ts +2560 -0
- package/src/routing/slots.ts +432 -0
- package/src/runtime/server.ts +3453 -0
- package/src/runtime/vendor.ts +1160 -0
- package/src/style-modules.d.ts +9 -0
- package/src/typegen.ts +151 -0
- package/src/types.ts +725 -0
- package/src/utils/ansi.ts +9 -0
- package/src/utils/content-type.ts +31 -0
- package/src/utils/decode.ts +7 -0
- package/src/utils/dev-profile.ts +31 -0
- package/src/utils/error-log.ts +29 -0
- package/src/utils/fs-cache.ts +31 -0
- package/src/utils/fs.ts +119 -0
- package/src/utils/html.ts +46 -0
- package/src/utils/serialize.ts +378 -0
- package/src/utils/source.ts +35 -0
- package/src/utils/verbose.ts +39 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Persisted next/font resolutions - the restart half of the in-memory `resolvedFontCache`. The
|
|
2
|
+
// bytes a resolution emits are already content-addressed on disk, but the resolution itself is not,
|
|
3
|
+
// so a dev restart would re-fetch every Google Fonts stylesheet and font file just to re-derive
|
|
4
|
+
// URLs it already emitted. This records the finished resolution next to those bytes and
|
|
5
|
+
// re-validates it with stats only:
|
|
6
|
+
// - every emitted file must still exist (a `pnext build` empties the dir), and
|
|
7
|
+
// - every local source file must still match the stat it was read at, so a font swapped while the
|
|
8
|
+
// server was not running re-resolves and re-emits.
|
|
9
|
+
// Nothing here is used by `pnext build`, which owns the directory it just wiped.
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { mkdir, stat } from 'node:fs/promises';
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import type { ResolvedConfig } from '../../../config';
|
|
15
|
+
import { restartCacheEnabled } from '../../../dev/restart-cache';
|
|
16
|
+
import { writeFileAtomic } from '../../../utils/fs';
|
|
17
|
+
import type { MetadataLink } from '../../../types';
|
|
18
|
+
|
|
19
|
+
export interface PersistableFont {
|
|
20
|
+
css: string;
|
|
21
|
+
preloads: MetadataLink[];
|
|
22
|
+
usesFonts: boolean;
|
|
23
|
+
files: string[];
|
|
24
|
+
/** Local font files the resolution read (google resolutions have none). */
|
|
25
|
+
sources?: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** `[file, mtimeMs, size]` — a local source and the stat it was resolved at. */
|
|
29
|
+
type SourceStat = [string, number, number];
|
|
30
|
+
|
|
31
|
+
interface Entry extends PersistableFont {
|
|
32
|
+
sourceStats: SourceStat[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface IndexFile {
|
|
36
|
+
version: number;
|
|
37
|
+
/** Content hash of the font runtime, so an upgrade never serves its output. */
|
|
38
|
+
runtime: string;
|
|
39
|
+
fonts: Record<string, Entry>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Bumped whenever a record's shape changes; an older index is simply ignored. */
|
|
43
|
+
const INDEX_VERSION = 1;
|
|
44
|
+
|
|
45
|
+
interface FontIndex {
|
|
46
|
+
file: string;
|
|
47
|
+
fonts: Map<string, Entry>;
|
|
48
|
+
dirty: boolean;
|
|
49
|
+
flush?: Timer;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const indexes = new Map<string, FontIndex>();
|
|
53
|
+
|
|
54
|
+
function fontIndex(config: ResolvedConfig): FontIndex {
|
|
55
|
+
const file = path.join(config.outPath, 'cache', 'fonts', 'index.json');
|
|
56
|
+
const existing = indexes.get(file);
|
|
57
|
+
if (existing) return existing;
|
|
58
|
+
const created: FontIndex = { file, fonts: readIndex(file), dirty: false };
|
|
59
|
+
indexes.set(file, created);
|
|
60
|
+
process.on('exit', () => {
|
|
61
|
+
if (!created.dirty) return;
|
|
62
|
+
created.dirty = false;
|
|
63
|
+
try {
|
|
64
|
+
writeFileSync(created.file, serializeIndex(created.fonts));
|
|
65
|
+
} catch {
|
|
66
|
+
// Best effort: a missing index only costs the next boot a re-resolve.
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return created;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** The recorded resolution for `key`, or undefined when it no longer describes disk. */
|
|
73
|
+
export async function persistedFont(
|
|
74
|
+
config: ResolvedConfig,
|
|
75
|
+
key: string,
|
|
76
|
+
): Promise<PersistableFont | undefined> {
|
|
77
|
+
if (!restartCacheEnabled()) return undefined;
|
|
78
|
+
const entry = fontIndex(config).fonts.get(key);
|
|
79
|
+
if (!entry) return undefined;
|
|
80
|
+
if (!entry.files.every(file => existsSync(file))) return undefined;
|
|
81
|
+
const stats = await Promise.all(
|
|
82
|
+
entry.sourceStats.map(async ([file, mtimeMs, size]) => {
|
|
83
|
+
const current = await stat(file).catch(() => undefined);
|
|
84
|
+
return current?.mtimeMs === mtimeMs && current.size === size;
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
if (!stats.every(Boolean)) return undefined;
|
|
88
|
+
return entry;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Record a finished resolution. Failures are non-fatal — they cost a re-resolve. */
|
|
92
|
+
export async function persistFont(config: ResolvedConfig, key: string, font: PersistableFont) {
|
|
93
|
+
const index = fontIndex(config);
|
|
94
|
+
const sourceStats = await Promise.all(
|
|
95
|
+
(font.sources ?? []).map(async (file): Promise<SourceStat | undefined> => {
|
|
96
|
+
const stats = await stat(file).catch(() => undefined);
|
|
97
|
+
return stats ? [file, stats.mtimeMs, stats.size] : undefined;
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
// A source that vanished mid-resolve must not be recorded as validated.
|
|
101
|
+
if (sourceStats.some(entry => entry === undefined)) return;
|
|
102
|
+
index.fonts.set(key, { ...font, sourceStats: sourceStats as SourceStat[] });
|
|
103
|
+
persist(index);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function persist(index: FontIndex) {
|
|
107
|
+
index.dirty = true;
|
|
108
|
+
if (index.flush) return;
|
|
109
|
+
index.flush = setTimeout(async () => {
|
|
110
|
+
index.flush = undefined;
|
|
111
|
+
if (!index.dirty) return;
|
|
112
|
+
const contents = serializeIndex(index.fonts);
|
|
113
|
+
try {
|
|
114
|
+
await mkdir(path.dirname(index.file), { recursive: true });
|
|
115
|
+
await writeFileAtomic(index.file, contents);
|
|
116
|
+
index.dirty = false;
|
|
117
|
+
} catch {
|
|
118
|
+
// A write that lost a race with a cache wipe must not look persisted.
|
|
119
|
+
}
|
|
120
|
+
}, 50);
|
|
121
|
+
// NOT unref'd: under the dev server this timer never fired, so the index was never written and
|
|
122
|
+
// every restart re-resolved every font over the network. The `exit` handler above still covers a
|
|
123
|
+
// process exit inside the window.
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function readIndex(file: string) {
|
|
127
|
+
const fonts = new Map<string, Entry>();
|
|
128
|
+
let parsed: IndexFile | undefined;
|
|
129
|
+
try {
|
|
130
|
+
parsed = JSON.parse(readFileSync(file, 'utf8')) as IndexFile;
|
|
131
|
+
} catch {
|
|
132
|
+
return fonts;
|
|
133
|
+
}
|
|
134
|
+
if (parsed?.version !== INDEX_VERSION || parsed.runtime !== runtimeFingerprint()) {
|
|
135
|
+
return fonts;
|
|
136
|
+
}
|
|
137
|
+
for (const [key, entry] of Object.entries(parsed.fonts ?? {})) {
|
|
138
|
+
if (entry && Array.isArray(entry.files) && Array.isArray(entry.sourceStats)) {
|
|
139
|
+
fonts.set(key, entry);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return fonts;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function serializeIndex(fonts: Map<string, Entry>) {
|
|
146
|
+
return JSON.stringify({
|
|
147
|
+
version: INDEX_VERSION,
|
|
148
|
+
runtime: runtimeFingerprint(),
|
|
149
|
+
fonts: Object.fromEntries(fonts),
|
|
150
|
+
} satisfies IndexFile);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// The CSS a resolution emits is shaped entirely by this directory's sources, so
|
|
154
|
+
// editing the font runtime must retire its records the same way editing a font
|
|
155
|
+
// does. Four small files, once per process.
|
|
156
|
+
let fingerprint: string | undefined;
|
|
157
|
+
|
|
158
|
+
function runtimeFingerprint() {
|
|
159
|
+
if (fingerprint !== undefined) return fingerprint;
|
|
160
|
+
const hash = createHash('sha256');
|
|
161
|
+
for (const entry of ['runtime.ts', 'google.ts', 'local.ts', 'shared.ts']) {
|
|
162
|
+
const file = new URL(entry, import.meta.url).pathname;
|
|
163
|
+
try {
|
|
164
|
+
hash.update(`${entry}:${Bun.hash(readFileSync(file)).toString(36)}\0`);
|
|
165
|
+
} catch {
|
|
166
|
+
// ignore unreadable entries
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
fingerprint = hash.digest('hex').slice(0, 16);
|
|
170
|
+
return fingerprint;
|
|
171
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-bundle variant of the next/font runtime.
|
|
3
|
+
*
|
|
4
|
+
* A `'use client'` component that calls `next/font/google` or `next/font/local` needs ONLY the
|
|
5
|
+
* pre-hashed className/variable/style off the font object - the actual CSS and font files are emitted
|
|
6
|
+
* and served by the SERVER runtime and already present in the SSR'd HTML. So this entry imports NOTHING
|
|
7
|
+
* from `node:*`, registers NO response finalizers at module scope, and derives className/variable/style
|
|
8
|
+
* from the SAME client-safe shared logic the server uses, so the hashes match exactly.
|
|
9
|
+
*
|
|
10
|
+
* rewriteNextFontSource targets this file for CLIENT builds and runtime.ts for SERVER builds.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
googleFontNaming,
|
|
15
|
+
localFontNaming,
|
|
16
|
+
fontStyle,
|
|
17
|
+
type GoogleFontOptions,
|
|
18
|
+
type LocalFontOptions,
|
|
19
|
+
type NextFontWithVariable,
|
|
20
|
+
} from './shared';
|
|
21
|
+
|
|
22
|
+
export type {
|
|
23
|
+
FontDisplay,
|
|
24
|
+
GoogleFontOptions,
|
|
25
|
+
LocalFontOptions,
|
|
26
|
+
LocalFontSource,
|
|
27
|
+
NextFont,
|
|
28
|
+
NextFontWithVariable,
|
|
29
|
+
} from './shared';
|
|
30
|
+
|
|
31
|
+
function fontObject(naming: {
|
|
32
|
+
className: string;
|
|
33
|
+
variable: string;
|
|
34
|
+
hasVariable: boolean;
|
|
35
|
+
style: NextFontWithVariable['style'];
|
|
36
|
+
}): NextFontWithVariable {
|
|
37
|
+
// Plain data object: no registration side effects (the server already emitted
|
|
38
|
+
// the CSS/assets). Client code reads className/variable/style off this. The
|
|
39
|
+
// `variable` key is omitted when the loader call passed no `variable` option,
|
|
40
|
+
// matching Next (a `toEqual` on the font object would otherwise see an extra
|
|
41
|
+
// key).
|
|
42
|
+
const font: NextFontWithVariable = {
|
|
43
|
+
className: naming.className,
|
|
44
|
+
style: naming.style,
|
|
45
|
+
} as NextFontWithVariable;
|
|
46
|
+
if (naming.hasVariable) font.variable = naming.variable;
|
|
47
|
+
return font;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function googleFont(family: string) {
|
|
51
|
+
return (options: GoogleFontOptions = {}): NextFontWithVariable =>
|
|
52
|
+
fontObject(googleFontNaming(family, options));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface LocalFontLoader {
|
|
56
|
+
(options: LocalFontOptions): NextFontWithVariable;
|
|
57
|
+
withFile: typeof localFontWithFile;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function localFontWithFile(callerFile: string | undefined, family?: string) {
|
|
61
|
+
return (options: LocalFontOptions): NextFontWithVariable =>
|
|
62
|
+
fontObject({
|
|
63
|
+
...localFontNaming(callerFile, options),
|
|
64
|
+
...(family ? { fontFamily: family, style: fontStyle(family, options, options.fallback ?? []) } : {}),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const localFont: LocalFontLoader = Object.assign(
|
|
69
|
+
(options: LocalFontOptions) => localFontWithFile(undefined)(options),
|
|
70
|
+
{ withFile: localFontWithFile },
|
|
71
|
+
);
|