@wular/pnext 0.0.4 → 0.0.6
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 +11 -11
- package/bin/pnext +1 -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 +1 -1
- package/reference/config.md +2 -2
- package/reference/css.md +13 -9
- package/reference/dev.md +1 -1
- package/reference/metadata.md +7 -7
- package/reference/navigation.md +35 -28
- package/reference/performance.md +70 -70
- package/reference/rendering.md +17 -17
- package/reference/routing.md +17 -17
- package/reference/typegen.md +12 -8
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +113 -109
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +49 -52
- 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 +71 -63
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +88 -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 +794 -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 +17 -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 +1988 -1992
- package/src/{api → client}/router/types.ts +93 -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 +69 -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 +2076 -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 +69 -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 +952 -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 +425 -404
- package/src/styles.d.ts +9 -0
- package/src/types.ts +320 -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/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
package/src/css/postcss.ts
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
// on the CSS worker thread (./worker.ts) rather than the event loop:
|
|
3
3
|
// Tailwind v4's postcss plugin is synchronous CPU work — its oxide scan and
|
|
4
4
|
// compile starved every concurrent request while it ran in-process.
|
|
5
|
-
import { createRequire } from 'node:module'
|
|
6
|
-
import { existsSync, readFileSync } from 'node:fs'
|
|
7
|
-
import { writeFile } from 'node:fs/promises'
|
|
8
|
-
import path from 'node:path'
|
|
9
|
-
import { pathToFileURL } from 'node:url'
|
|
10
|
-
import { readText } from '../utils/fs'
|
|
5
|
+
import { createRequire } from 'node:module'
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
7
|
+
import { writeFile } from 'node:fs/promises'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
import { pathToFileURL } from 'node:url'
|
|
10
|
+
import { readText } from '../utils/fs'
|
|
11
11
|
|
|
12
12
|
export interface PostcssOptions {
|
|
13
|
-
dev?: boolean
|
|
13
|
+
dev?: boolean
|
|
14
14
|
/** pnext's output directory — kept out of Tailwind's content scan. */
|
|
15
|
-
outDir?: string
|
|
15
|
+
outDir?: string
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// One long-lived processor per root+mode. Keeping it alive is what makes dev fast: Tailwind v4's postcss
|
|
@@ -20,45 +20,45 @@ export interface PostcssOptions {
|
|
|
20
20
|
// instead of a CLI spawn plus a full project re-scan. It also means other plugins in the config actually
|
|
21
21
|
// execute - the old CLI path treated postcss.config purely as a Tailwind trigger. Config-file edits need a
|
|
22
22
|
// dev-server restart; Tailwind tracks its own dependencies and refreshes them itself.
|
|
23
|
-
const postcssProcessors = new Map<string, Promise<LoadedPostcss | undefined>>()
|
|
23
|
+
const postcssProcessors = new Map<string, Promise<LoadedPostcss | undefined>>()
|
|
24
24
|
|
|
25
25
|
interface PostcssProcessor {
|
|
26
|
-
process(css: string, options: { from: string; to: string }): PromiseLike<{ css: string }
|
|
26
|
+
process(css: string, options: { from: string; to: string }): PromiseLike<{ css: string }>
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/** A processor plus the `@source not` directives to append for it (if any). */
|
|
30
30
|
interface LoadedPostcss {
|
|
31
|
-
processor: PostcssProcessor
|
|
32
|
-
sources: string
|
|
31
|
+
processor: PostcssProcessor
|
|
32
|
+
sources: string
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
type PostcssPluginFactory = (options?: unknown) => unknown
|
|
35
|
+
type PostcssPluginFactory = (options?: unknown) => unknown
|
|
36
36
|
|
|
37
37
|
interface PostcssConfig {
|
|
38
|
-
plugins?: Record<string, unknown> | unknown[]
|
|
38
|
+
plugins?: Record<string, unknown> | unknown[]
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function postcssConfigFile(root: string) {
|
|
42
42
|
for (const file of ['postcss.config.cjs', 'postcss.config.js', 'postcss.config.mjs']) {
|
|
43
|
-
const full = path.join(root, file)
|
|
44
|
-
if (existsSync(full)) return full
|
|
43
|
+
const full = path.join(root, file)
|
|
44
|
+
if (existsSync(full)) return full
|
|
45
45
|
}
|
|
46
|
-
return undefined
|
|
46
|
+
return undefined
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/** Build (or reuse) the processor for this root+mode without processing a file. */
|
|
50
50
|
export function loadPostcss(root: string, options: PostcssOptions) {
|
|
51
|
-
const key = `${root}\0${options.dev ? 'dev' : 'build'}\0${options.outDir ?? ''}
|
|
52
|
-
let processor = postcssProcessors.get(key)
|
|
51
|
+
const key = `${root}\0${options.dev ? 'dev' : 'build'}\0${options.outDir ?? ''}`
|
|
52
|
+
let processor = postcssProcessors.get(key)
|
|
53
53
|
if (!processor) {
|
|
54
54
|
processor = createPostcssProcessor(root, options).catch((error: unknown) => {
|
|
55
55
|
// Drop failed setups so a fixed config or install is retried.
|
|
56
|
-
postcssProcessors.delete(key)
|
|
57
|
-
throw error
|
|
58
|
-
})
|
|
59
|
-
postcssProcessors.set(key, processor)
|
|
56
|
+
postcssProcessors.delete(key)
|
|
57
|
+
throw error
|
|
58
|
+
})
|
|
59
|
+
postcssProcessors.set(key, processor)
|
|
60
60
|
}
|
|
61
|
-
return processor
|
|
61
|
+
return processor
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
export async function runPostcss(
|
|
@@ -67,43 +67,42 @@ export async function runPostcss(
|
|
|
67
67
|
options: PostcssOptions,
|
|
68
68
|
fromSource?: string,
|
|
69
69
|
) {
|
|
70
|
-
const loaded = await loadPostcss(root, options)
|
|
71
|
-
if (!loaded) return
|
|
70
|
+
const loaded = await loadPostcss(root, options)
|
|
71
|
+
if (!loaded) return
|
|
72
72
|
// `from` labels the input for postcss plugins' diagnostics/source maps. Point
|
|
73
73
|
// it at the original CSS source (not the synthesized bundle outfile) so
|
|
74
74
|
// plugins like `@tailwindcss/postcss` report the real path (e.g. its
|
|
75
75
|
// `DEBUG=tailwindcss` marker keys off `result.opts.from`). We still write the
|
|
76
76
|
// processed output back to the bundle outfile via `to`.
|
|
77
|
-
const from = fromSource ?? cssFile
|
|
77
|
+
const from = fromSource ?? cssFile
|
|
78
78
|
// The scan directives go last so they don't shift the line numbers plugins
|
|
79
79
|
// report against the real source; `@source` is order-independent to Tailwind.
|
|
80
80
|
const result = await loaded.processor.process((await readText(cssFile)) + loaded.sources, {
|
|
81
81
|
from,
|
|
82
82
|
to: cssFile,
|
|
83
|
-
})
|
|
84
|
-
await writeFile(cssFile, result.css)
|
|
83
|
+
})
|
|
84
|
+
await writeFile(cssFile, result.css)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
async function createPostcssProcessor(root: string, options: PostcssOptions) {
|
|
88
|
-
const configFile = postcssConfigFile(root)
|
|
89
|
-
if (!configFile) return undefined
|
|
88
|
+
const configFile = postcssConfigFile(root)
|
|
89
|
+
if (!configFile) return undefined
|
|
90
90
|
const loaded = (await import(pathToFileURL(configFile).href)) as
|
|
91
|
-
| PostcssConfig
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const appRequire = createRequire(path.join(root, 'package.json'));
|
|
91
|
+
PostcssConfig | { default: PostcssConfig }
|
|
92
|
+
const config = 'default' in loaded && loaded.default ? loaded.default : loaded
|
|
93
|
+
const plugins = postcssPlugins(root, config as PostcssConfig, options)
|
|
94
|
+
if (plugins.length === 0) return undefined
|
|
95
|
+
const appRequire = createRequire(path.join(root, 'package.json'))
|
|
97
96
|
const postcss = interopDefault(resolvePostcss(appRequire)) as (
|
|
98
97
|
plugins: unknown[],
|
|
99
|
-
) => PostcssProcessor
|
|
98
|
+
) => PostcssProcessor
|
|
100
99
|
const tailwind = pluginEntries(config as PostcssConfig).some(
|
|
101
100
|
([specifier, pluginOptions]) => specifier === '@tailwindcss/postcss' && pluginOptions !== false,
|
|
102
|
-
)
|
|
101
|
+
)
|
|
103
102
|
return {
|
|
104
103
|
processor: postcss(plugins),
|
|
105
104
|
sources: tailwind ? scanExclusions(root, appRequire, options) : '',
|
|
106
|
-
}
|
|
105
|
+
}
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
/**
|
|
@@ -116,32 +115,32 @@ async function createPostcssProcessor(root: string, options: PostcssOptions) {
|
|
|
116
115
|
*/
|
|
117
116
|
function scanExclusions(root: string, appRequire: NodeJS.Require, options: PostcssOptions) {
|
|
118
117
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
119
|
-
if (process.env.PNEXT_TAILWIND_SCAN_ALL) return ''
|
|
118
|
+
if (process.env.PNEXT_TAILWIND_SCAN_ALL) return ''
|
|
120
119
|
// `@source not` landed in Tailwind 4.1; older versions error on the at-rule.
|
|
121
|
-
const [major, minor] = packageVersion(appRequire, '@tailwindcss/postcss')
|
|
122
|
-
if (major < 4 || (major === 4 && minor < 1)) return ''
|
|
123
|
-
const dirs = ['node_modules', '.next', options.outDir ?? '.pnext']
|
|
120
|
+
const [major, minor] = packageVersion(appRequire, '@tailwindcss/postcss')
|
|
121
|
+
if (major < 4 || (major === 4 && minor < 1)) return ''
|
|
122
|
+
const dirs = ['node_modules', '.next', options.outDir ?? '.pnext']
|
|
124
123
|
const excluded = [...new Set(dirs.map(dir => path.resolve(root, dir)))].filter(
|
|
125
124
|
dir => dir.startsWith(root + path.sep) && existsSync(dir),
|
|
126
|
-
)
|
|
127
|
-
if (excluded.length === 0) return ''
|
|
125
|
+
)
|
|
126
|
+
if (excluded.length === 0) return ''
|
|
128
127
|
// Leading and trailing newlines keep the stylesheet's own first and last
|
|
129
128
|
// lines exactly as they were, so the emitted CSS stays byte-identical.
|
|
130
129
|
return `\n${excluded
|
|
131
130
|
.map(dir => `@source not ${JSON.stringify(dir.split(path.sep).join('/'))};`)
|
|
132
|
-
.join('\n')}\n
|
|
131
|
+
.join('\n')}\n`
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
/** `[major, minor]` of a resolvable package, or `[0, 0]` when unknown. */
|
|
136
135
|
function packageVersion(req: NodeJS.Require, name: string): [number, number] {
|
|
137
136
|
try {
|
|
138
137
|
const pkg = JSON.parse(readFileSync(req.resolve(`${name}/package.json`), 'utf8')) as {
|
|
139
|
-
version?: string
|
|
140
|
-
}
|
|
141
|
-
const [major, minor] = (pkg.version ?? '').split('.')
|
|
142
|
-
return [Number.parseInt(major ?? '', 10) || 0, Number.parseInt(minor ?? '', 10) || 0]
|
|
138
|
+
version?: string
|
|
139
|
+
}
|
|
140
|
+
const [major, minor] = (pkg.version ?? '').split('.')
|
|
141
|
+
return [Number.parseInt(major ?? '', 10) || 0, Number.parseInt(minor ?? '', 10) || 0]
|
|
143
142
|
} catch {
|
|
144
|
-
return [0, 0]
|
|
143
|
+
return [0, 0]
|
|
145
144
|
}
|
|
146
145
|
}
|
|
147
146
|
|
|
@@ -152,28 +151,28 @@ function pluginEntries(config: PostcssConfig): [unknown, unknown][] {
|
|
|
152
151
|
? ([entry[0], entry[1]] as [unknown, unknown])
|
|
153
152
|
: ([entry, undefined] as [unknown, unknown]),
|
|
154
153
|
)
|
|
155
|
-
: Object.entries(config.plugins ?? {})
|
|
154
|
+
: Object.entries(config.plugins ?? {})
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
function postcssPlugins(root: string, config: PostcssConfig, options: PostcssOptions) {
|
|
159
|
-
const appRequire = createRequire(path.join(root, 'package.json'))
|
|
160
|
-
const entries = pluginEntries(config)
|
|
158
|
+
const appRequire = createRequire(path.join(root, 'package.json'))
|
|
159
|
+
const entries = pluginEntries(config)
|
|
161
160
|
|
|
162
|
-
const plugins: unknown[] = []
|
|
161
|
+
const plugins: unknown[] = []
|
|
163
162
|
for (const [specifier, pluginOptions] of entries) {
|
|
164
|
-
if (pluginOptions === false) continue
|
|
163
|
+
if (pluginOptions === false) continue
|
|
165
164
|
if (typeof specifier !== 'string') {
|
|
166
165
|
// Already-instantiated plugin object or factory in an array config.
|
|
167
|
-
if (specifier) plugins.push(specifier)
|
|
168
|
-
continue
|
|
166
|
+
if (specifier) plugins.push(specifier)
|
|
167
|
+
continue
|
|
169
168
|
}
|
|
170
|
-
const factory = interopDefault(appRequire(specifier) as unknown)
|
|
171
|
-
const resolvedOptions = pluginOptionsFor(root, specifier, pluginOptions, options)
|
|
169
|
+
const factory = interopDefault(appRequire(specifier) as unknown)
|
|
170
|
+
const resolvedOptions = pluginOptionsFor(root, specifier, pluginOptions, options)
|
|
172
171
|
plugins.push(
|
|
173
172
|
typeof factory === 'function' ? (factory as PostcssPluginFactory)(resolvedOptions) : factory,
|
|
174
|
-
)
|
|
173
|
+
)
|
|
175
174
|
}
|
|
176
|
-
return plugins
|
|
175
|
+
return plugins
|
|
177
176
|
}
|
|
178
177
|
|
|
179
178
|
function pluginOptionsFor(
|
|
@@ -182,14 +181,14 @@ function pluginOptionsFor(
|
|
|
182
181
|
userOptions: unknown,
|
|
183
182
|
options: PostcssOptions,
|
|
184
183
|
) {
|
|
185
|
-
if (specifier !== '@tailwindcss/postcss') return userOptions
|
|
184
|
+
if (specifier !== '@tailwindcss/postcss') return userOptions
|
|
186
185
|
// Scan candidates from the app root — the bundled css Tailwind reads lives
|
|
187
186
|
// under .pnext, where a default input-relative scan would find nothing.
|
|
188
187
|
return {
|
|
189
188
|
base: root,
|
|
190
189
|
optimize: options.dev ? false : { minify: true },
|
|
191
190
|
...(typeof userOptions === 'object' && userOptions !== null ? userOptions : {}),
|
|
192
|
-
}
|
|
191
|
+
}
|
|
193
192
|
}
|
|
194
193
|
|
|
195
194
|
function resolvePostcss(appRequire: NodeJS.Require): unknown {
|
|
@@ -198,39 +197,39 @@ function resolvePostcss(appRequire: NodeJS.Require): unknown {
|
|
|
198
197
|
// dependency, which the package manager hoists to the app's top-level node_modules, so requiring
|
|
199
198
|
// 'postcss' from the app would return PostCSS 7 and a modern app plugin using the v8 API throws. Prefer
|
|
200
199
|
// the app's postcss only when it is already v8+, otherwise fall back to pnext's own.
|
|
201
|
-
let appPostcss: unknown
|
|
200
|
+
let appPostcss: unknown
|
|
202
201
|
try {
|
|
203
|
-
appPostcss = appRequire('postcss')
|
|
204
|
-
if (packageVersion(appRequire, 'postcss')[0] >= 8) return appPostcss
|
|
202
|
+
appPostcss = appRequire('postcss')
|
|
203
|
+
if (packageVersion(appRequire, 'postcss')[0] >= 8) return appPostcss
|
|
205
204
|
} catch {
|
|
206
205
|
// App has no resolvable postcss; fall through to pnext's own / plugin copy.
|
|
207
206
|
}
|
|
208
|
-
const ownPostcss = resolveOwnPostcss()
|
|
209
|
-
if (ownPostcss) return ownPostcss
|
|
207
|
+
const ownPostcss = resolveOwnPostcss()
|
|
208
|
+
if (ownPostcss) return ownPostcss
|
|
210
209
|
try {
|
|
211
210
|
// A Tailwind-based app ships a v8 postcss under its plugin package.
|
|
212
|
-
const pluginPackage = appRequire.resolve('@tailwindcss/postcss/package.json')
|
|
213
|
-
return createRequire(pluginPackage)('postcss')
|
|
211
|
+
const pluginPackage = appRequire.resolve('@tailwindcss/postcss/package.json')
|
|
212
|
+
return createRequire(pluginPackage)('postcss')
|
|
214
213
|
} catch {
|
|
215
214
|
// Last resort: whatever the app resolved (even if <8) — better than nothing.
|
|
216
|
-
if (appPostcss) return appPostcss
|
|
217
|
-
throw new Error('Could not resolve a PostCSS installation for the CSS pipeline.')
|
|
215
|
+
if (appPostcss) return appPostcss
|
|
216
|
+
throw new Error('Could not resolve a PostCSS installation for the CSS pipeline.')
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
219
|
|
|
221
220
|
/** pnext's own PostCSS 8 (mirrors Next's bundled copy), or undefined. */
|
|
222
221
|
function resolveOwnPostcss(): unknown {
|
|
223
222
|
try {
|
|
224
|
-
const ownRequire = createRequire(import.meta.url)
|
|
225
|
-
if (packageVersion(ownRequire, 'postcss')[0] >= 8) return ownRequire('postcss')
|
|
223
|
+
const ownRequire = createRequire(import.meta.url)
|
|
224
|
+
if (packageVersion(ownRequire, 'postcss')[0] >= 8) return ownRequire('postcss')
|
|
226
225
|
} catch {
|
|
227
226
|
// pnext's install carries no resolvable postcss; caller falls back.
|
|
228
227
|
}
|
|
229
|
-
return undefined
|
|
228
|
+
return undefined
|
|
230
229
|
}
|
|
231
230
|
|
|
232
231
|
function interopDefault(mod: unknown): unknown {
|
|
233
|
-
if (typeof mod === 'function') return mod
|
|
234
|
-
if (mod && typeof mod === 'object' && 'default' in mod && mod.default) return mod.default
|
|
235
|
-
return mod
|
|
232
|
+
if (typeof mod === 'function') return mod
|
|
233
|
+
if (mod && typeof mod === 'object' && 'default' in mod && mod.default) return mod.default
|
|
234
|
+
return mod
|
|
236
235
|
}
|
package/src/css/worker.ts
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
// CSS worker entry — runs the postcss/Tailwind pipeline off the event loop.
|
|
2
2
|
// One message per built stylesheet; the processor cache in ./postcss.ts lives
|
|
3
3
|
// here for the worker's lifetime, so Tailwind stays incremental across rebuilds.
|
|
4
|
-
import { loadPostcss, runPostcss } from './postcss'
|
|
4
|
+
import { loadPostcss, runPostcss } from './postcss'
|
|
5
5
|
export type CssWorkerRequest = { id: number; root: string; dev: boolean; outDir?: string } & (
|
|
6
|
-
| { kind: '
|
|
7
|
-
|
|
8
|
-
);
|
|
6
|
+
{ kind: 'warm' } | { kind: 'process'; cssFile: string; from?: string }
|
|
7
|
+
)
|
|
9
8
|
|
|
10
9
|
export interface CssWorkerResponse {
|
|
11
|
-
id: number
|
|
12
|
-
error?: { name: string; message: string; stack?: string }
|
|
10
|
+
id: number
|
|
11
|
+
error?: { name: string; message: string; stack?: string }
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
declare const self: Worker
|
|
14
|
+
declare const self: Worker
|
|
16
15
|
|
|
17
16
|
self.onmessage = async (event: MessageEvent<CssWorkerRequest>) => {
|
|
18
|
-
const request = event.data
|
|
19
|
-
const reply = (response: CssWorkerResponse) => postMessage(response)
|
|
17
|
+
const request = event.data
|
|
18
|
+
const reply = (response: CssWorkerResponse) => postMessage(response)
|
|
20
19
|
try {
|
|
21
|
-
const options = { dev: request.dev, outDir: request.outDir }
|
|
22
|
-
if (request.kind === 'warm') await loadPostcss(request.root, options)
|
|
23
|
-
else await runPostcss(request.root, request.cssFile, options, request.from)
|
|
24
|
-
reply({ id: request.id })
|
|
20
|
+
const options = { dev: request.dev, outDir: request.outDir }
|
|
21
|
+
if (request.kind === 'warm') await loadPostcss(request.root, options)
|
|
22
|
+
else await runPostcss(request.root, request.cssFile, options, request.from)
|
|
23
|
+
reply({ id: request.id })
|
|
25
24
|
} catch (error) {
|
|
26
25
|
reply({
|
|
27
26
|
id: request.id,
|
|
@@ -29,6 +28,6 @@ self.onmessage = async (event: MessageEvent<CssWorkerRequest>) => {
|
|
|
29
28
|
error instanceof Error
|
|
30
29
|
? { name: error.name, message: error.message, stack: error.stack }
|
|
31
30
|
: { name: 'Error', message: String(error) },
|
|
32
|
-
})
|
|
31
|
+
})
|
|
33
32
|
}
|
|
34
|
-
}
|
|
33
|
+
}
|
|
@@ -2,34 +2,34 @@
|
|
|
2
2
|
//
|
|
3
3
|
// The dev route-client bundle resolves every module into its own `pnext-route-client` esbuild namespace, so
|
|
4
4
|
// a standalone esbuild plugin cannot intercept that graph the way it can a plain client build. This holder
|
|
5
|
-
// is the extension point
|
|
5
|
+
// is the extension point runtime/modules reads to turn a client-side import of a `'use server'` module into the
|
|
6
6
|
// RPC stub, without core statically importing compat/actions.
|
|
7
7
|
//
|
|
8
|
-
// Compat populates it; a pure-core app leaves it unset, and
|
|
9
|
-
// source module. Mirrors the routing/request-
|
|
8
|
+
// Compat populates it; a pure-core app leaves it unset, and runtime/modules treats every module as a normal
|
|
9
|
+
// source module. Mirrors the routing/request-environment.ts holder pattern.
|
|
10
10
|
|
|
11
|
-
/** Compat client-action bundler surface
|
|
11
|
+
/** Compat client-action bundler surface runtime/modules consults. */
|
|
12
12
|
export interface ClientActionBundler {
|
|
13
13
|
/**
|
|
14
14
|
* Ensure the client-action module set is discovered for the active dev import version (a dev reload bumps
|
|
15
15
|
* it). Awaited before a route-client build so the stub check below sees the current set - the discovery
|
|
16
16
|
* that used to run inline at startup/reload now happens lazily here. Idempotent per version.
|
|
17
17
|
*/
|
|
18
|
-
ensureArmed: () => Promise<void
|
|
18
|
+
ensureArmed: () => Promise<void>
|
|
19
19
|
/** True when `file` is a discovered `'use server'` module (stub it on the client). */
|
|
20
|
-
isClientActionModule: (file: string) => boolean
|
|
20
|
+
isClientActionModule: (file: string) => boolean
|
|
21
21
|
/** Generate the client fetch-stub source for an action module file. */
|
|
22
|
-
stubSource: (file: string) => Promise<string
|
|
22
|
+
stubSource: (file: string) => Promise<string>
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
let bundler: ClientActionBundler | undefined
|
|
25
|
+
let bundler: ClientActionBundler | undefined
|
|
26
26
|
|
|
27
27
|
/** Publish the compat client-action bundler (register-actions). */
|
|
28
28
|
export function setClientActionBundler(next: ClientActionBundler): void {
|
|
29
|
-
bundler = next
|
|
29
|
+
bundler = next
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/** The compat client-action bundler, or undefined for a pure-core app. */
|
|
33
33
|
export function getClientActionBundler(): ClientActionBundler | undefined {
|
|
34
|
-
return bundler
|
|
34
|
+
return bundler
|
|
35
35
|
}
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
// duplicates to one inode while every generation dir keeps a normal-looking
|
|
6
6
|
// path; eviction of one generation just drops its link, leaving the others
|
|
7
7
|
// (and the store's own link) intact.
|
|
8
|
-
import { createHash } from 'node:crypto'
|
|
9
|
-
import { link, mkdir, readFile, readdir, rm, stat, unlink } from 'node:fs/promises'
|
|
10
|
-
import path from 'node:path'
|
|
11
|
-
import { listFiles } from '../utils/fs'
|
|
8
|
+
import { createHash } from 'node:crypto'
|
|
9
|
+
import { link, mkdir, readFile, readdir, rm, stat, unlink } from 'node:fs/promises'
|
|
10
|
+
import path from 'node:path'
|
|
11
|
+
import { listFiles } from '../utils/fs'
|
|
12
12
|
|
|
13
13
|
export function clientChunkStoreDir(outPath: string) {
|
|
14
|
-
return path.join(outPath, 'cache', 'client-store')
|
|
14
|
+
return path.join(outPath, 'cache', 'client-store')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function contentHash(data: Buffer) {
|
|
18
|
-
return createHash('sha1').update(data).digest('hex')
|
|
18
|
+
return createHash('sha1').update(data).digest('hex')
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -25,31 +25,31 @@ function contentHash(data: Buffer) {
|
|
|
25
25
|
* file always ends up in place either way.
|
|
26
26
|
*/
|
|
27
27
|
export async function contentAddressDir(dir: string, storeDir: string) {
|
|
28
|
-
await mkdir(storeDir, { recursive: true })
|
|
29
|
-
const files = await listFiles(dir)
|
|
30
|
-
await Promise.all(files.map(file => contentAddressFile(file, storeDir)))
|
|
28
|
+
await mkdir(storeDir, { recursive: true })
|
|
29
|
+
const files = await listFiles(dir)
|
|
30
|
+
await Promise.all(files.map(file => contentAddressFile(file, storeDir)))
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
async function contentAddressFile(file: string, storeDir: string) {
|
|
34
|
-
const data = await readFile(file)
|
|
35
|
-
const storePath = path.join(storeDir, `${contentHash(data)}${path.extname(file)}`)
|
|
34
|
+
const data = await readFile(file)
|
|
35
|
+
const storePath = path.join(storeDir, `${contentHash(data)}${path.extname(file)}`)
|
|
36
36
|
if (!(await pathExists(storePath))) {
|
|
37
37
|
// Claim the store slot from this file's own bytes: link first (cheap, same
|
|
38
38
|
// device), and only fall back to a copy if that's impossible. Either way the
|
|
39
39
|
// original file stays at `file` — nothing below needs to re-link it there.
|
|
40
40
|
try {
|
|
41
|
-
await link(file, storePath)
|
|
42
|
-
return
|
|
41
|
+
await link(file, storePath)
|
|
42
|
+
return
|
|
43
43
|
} catch {
|
|
44
|
-
await copyFileFallback(file, storePath)
|
|
45
|
-
return
|
|
44
|
+
await copyFileFallback(file, storePath)
|
|
45
|
+
return
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
// Store already holds this content: swap the freshly-written file for a link
|
|
49
49
|
// to the shared inode so duplicate bytes stop being duplicate on disk.
|
|
50
50
|
try {
|
|
51
|
-
await unlink(file)
|
|
52
|
-
await link(storePath, file)
|
|
51
|
+
await unlink(file)
|
|
52
|
+
await link(storePath, file)
|
|
53
53
|
} catch {
|
|
54
54
|
// Cross-device or racing unlink: leave the original file in place, it is
|
|
55
55
|
// already correct content, just not deduped this time.
|
|
@@ -58,8 +58,8 @@ async function contentAddressFile(file: string, storeDir: string) {
|
|
|
58
58
|
|
|
59
59
|
async function copyFileFallback(file: string, storePath: string) {
|
|
60
60
|
try {
|
|
61
|
-
const data = await readFile(file)
|
|
62
|
-
await Bun.write(storePath, data)
|
|
61
|
+
const data = await readFile(file)
|
|
62
|
+
await Bun.write(storePath, data)
|
|
63
63
|
} catch {
|
|
64
64
|
// Best-effort: dedup is an optimization, not a correctness requirement.
|
|
65
65
|
}
|
|
@@ -68,7 +68,7 @@ async function copyFileFallback(file: string, storePath: string) {
|
|
|
68
68
|
async function pathExists(target: string) {
|
|
69
69
|
return stat(target)
|
|
70
70
|
.then(() => true)
|
|
71
|
-
.catch(() => false)
|
|
71
|
+
.catch(() => false)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
@@ -76,17 +76,17 @@ async function pathExists(target: string) {
|
|
|
76
76
|
* store's own hardlink is the only one left - every generation that once pointed at it has been evicted.
|
|
77
77
|
*/
|
|
78
78
|
export async function sweepClientChunkStore(storeDir: string) {
|
|
79
|
-
let entries: string[]
|
|
79
|
+
let entries: string[]
|
|
80
80
|
try {
|
|
81
|
-
entries = await readdir(storeDir)
|
|
81
|
+
entries = await readdir(storeDir)
|
|
82
82
|
} catch {
|
|
83
|
-
return
|
|
83
|
+
return
|
|
84
84
|
}
|
|
85
85
|
await Promise.allSettled(
|
|
86
86
|
entries.map(async entry => {
|
|
87
|
-
const full = path.join(storeDir, entry)
|
|
88
|
-
const info = await stat(full).catch(() => null)
|
|
89
|
-
if (info && info.nlink <= 1) await rm(full, { force: true })
|
|
87
|
+
const full = path.join(storeDir, entry)
|
|
88
|
+
const info = await stat(full).catch(() => null)
|
|
89
|
+
if (info && info.nlink <= 1) await rm(full, { force: true })
|
|
90
90
|
}),
|
|
91
|
-
)
|
|
91
|
+
)
|
|
92
92
|
}
|