@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/resolve/imports.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
3
|
import {
|
|
4
4
|
probeFile,
|
|
5
5
|
probePackageTarget,
|
|
@@ -8,101 +8,101 @@ import {
|
|
|
8
8
|
setEngineTsConfigPath,
|
|
9
9
|
splitResourceQuery,
|
|
10
10
|
tsConfigFileFor,
|
|
11
|
-
} from './engine'
|
|
12
|
-
import { onExtensionHostReset } from '../extensions'
|
|
11
|
+
} from './engine'
|
|
12
|
+
import { onExtensionHostReset } from '../extensions'
|
|
13
13
|
|
|
14
14
|
// Conditions for "is this a local source file" lookups. Ordered to mirror the
|
|
15
15
|
// preference a bundler applies, though `exports` key order ultimately decides.
|
|
16
|
-
const localConditions = ['source', 'import', 'browser', 'node', 'default', 'require']
|
|
16
|
+
const localConditions = ['source', 'import', 'browser', 'node', 'default', 'require']
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Override the resolver's extension probe order (next.config `resolveExtensions`).
|
|
20
20
|
* Pass undefined (or []) to restore the built-in source-extension order.
|
|
21
21
|
*/
|
|
22
22
|
export function setResolveExtensions(extensions: readonly string[] | undefined): void {
|
|
23
|
-
setEngineExtensions(extensions)
|
|
24
|
-
clearVendorPackageResolutions()
|
|
23
|
+
setEngineExtensions(extensions)
|
|
24
|
+
clearVendorPackageResolutions()
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// B7 (serverExternalPackages / transpilePackages): the node_modules bundle-vs-
|
|
28
28
|
// external decision is driven by next.config, which lives in compat. Core keeps
|
|
29
29
|
// no static edge into compat, so compat registers the policy here (a setter) and
|
|
30
|
-
// core's server compile sites (
|
|
30
|
+
// core's server compile sites (runtime/modules.ts, runtime/loader.ts) consult it.
|
|
31
31
|
export interface ExternalPackagePolicy {
|
|
32
32
|
/** Force-external (never bundle) — serverExternalPackages + built-ins. */
|
|
33
|
-
external: (packageName: string) => boolean
|
|
33
|
+
external: (packageName: string) => boolean
|
|
34
34
|
/** Force-bundle + transpile (incl. node_modules TS/CSS/font) — transpilePackages. */
|
|
35
|
-
transpile: (packageName: string) => boolean
|
|
35
|
+
transpile: (packageName: string) => boolean
|
|
36
36
|
/**
|
|
37
37
|
* The same rule as a LIST, where one exists: bundler filters need names up front, and probing
|
|
38
38
|
* `transpile` per installed package is expensive. Absent, callers must assume any package may
|
|
39
39
|
* transpile.
|
|
40
40
|
*/
|
|
41
|
-
transpiled?: () => readonly string[]
|
|
41
|
+
transpiled?: () => readonly string[]
|
|
42
42
|
/** ESM external mode for package exports interop. */
|
|
43
|
-
esmExternals: () => boolean | 'loose'
|
|
43
|
+
esmExternals: () => boolean | 'loose'
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export type ExternalLoadTarget = 'server' | 'edge' | 'client' | 'client-ssr'
|
|
46
|
+
export type ExternalLoadTarget = 'server' | 'edge' | 'client' | 'client-ssr'
|
|
47
47
|
|
|
48
48
|
export interface ExternalLoadContext {
|
|
49
|
-
root: string
|
|
50
|
-
fromFile: string
|
|
51
|
-
specifier: string
|
|
52
|
-
target: ExternalLoadTarget
|
|
49
|
+
root: string
|
|
50
|
+
fromFile: string
|
|
51
|
+
specifier: string
|
|
52
|
+
target: ExternalLoadTarget
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export type ExternalLoadResolver = (context: ExternalLoadContext) => string | undefined
|
|
55
|
+
export type ExternalLoadResolver = (context: ExternalLoadContext) => string | undefined
|
|
56
56
|
|
|
57
57
|
const noExternalPolicy: ExternalPackagePolicy = {
|
|
58
58
|
external: () => false,
|
|
59
59
|
transpile: () => false,
|
|
60
60
|
esmExternals: () => true,
|
|
61
|
-
}
|
|
62
|
-
let externalPackagePolicy: ExternalPackagePolicy = noExternalPolicy
|
|
63
|
-
let externalLoadResolver: ExternalLoadResolver | undefined
|
|
61
|
+
}
|
|
62
|
+
let externalPackagePolicy: ExternalPackagePolicy = noExternalPolicy
|
|
63
|
+
let externalLoadResolver: ExternalLoadResolver | undefined
|
|
64
64
|
|
|
65
65
|
/** Install the compat-driven external/transpile package policy (see B7). */
|
|
66
66
|
export function setExternalPackagePolicy(policy: ExternalPackagePolicy | undefined): void {
|
|
67
|
-
externalPackagePolicy = policy ?? noExternalPolicy
|
|
67
|
+
externalPackagePolicy = policy ?? noExternalPolicy
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export function getExternalPackagePolicy(): ExternalPackagePolicy {
|
|
71
|
-
return externalPackagePolicy
|
|
71
|
+
return externalPackagePolicy
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/** Install an optional concrete-file resolver for external runtime loads. */
|
|
75
75
|
export function setExternalLoadResolver(resolver: ExternalLoadResolver | undefined): void {
|
|
76
|
-
externalLoadResolver = resolver
|
|
77
|
-
externalLoadTargets.clear()
|
|
76
|
+
externalLoadResolver = resolver
|
|
77
|
+
externalLoadTargets.clear()
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Every bare import evaluated by the server runtime reaches the resolve hook, and an external one costs a
|
|
81
81
|
// full oxc package resolve there. Keyed on the RESOLUTION ROOT - the only thing the resolver reads out of
|
|
82
82
|
// `fromFile` - for the reason `resolveVendorPackageSpecifier` documents: keying on the importer misses on
|
|
83
83
|
// nearly every call.
|
|
84
|
-
const externalLoadTargets = new Map<string, string | undefined>()
|
|
84
|
+
const externalLoadTargets = new Map<string, string | undefined>()
|
|
85
85
|
|
|
86
86
|
export function resolveExternalLoadTarget(context: ExternalLoadContext): string | undefined {
|
|
87
|
-
if (!externalLoadResolver) return undefined
|
|
87
|
+
if (!externalLoadResolver) return undefined
|
|
88
88
|
// `#imports` resolve from the importer's OWN package, so they are not
|
|
89
89
|
// shareable across a resolution root; they stay uncached.
|
|
90
|
-
if (context.specifier.startsWith('#')) return externalLoadResolver(context)
|
|
91
|
-
const key = `${context.target}\0${resolutionRootForFile(context.root, context.fromFile)}\0${context.specifier}
|
|
92
|
-
if (externalLoadTargets.has(key)) return externalLoadTargets.get(key)
|
|
93
|
-
const target = externalLoadResolver(context)
|
|
94
|
-
externalLoadTargets.set(key, target)
|
|
95
|
-
return target
|
|
90
|
+
if (context.specifier.startsWith('#')) return externalLoadResolver(context)
|
|
91
|
+
const key = `${context.target}\0${resolutionRootForFile(context.root, context.fromFile)}\0${context.specifier}`
|
|
92
|
+
if (externalLoadTargets.has(key)) return externalLoadTargets.get(key)
|
|
93
|
+
const target = externalLoadResolver(context)
|
|
94
|
+
externalLoadTargets.set(key, target)
|
|
95
|
+
return target
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/** The npm package name owning a bare specifier (`foo/bar` -> `foo`, scoped ok). */
|
|
99
99
|
export function packageNameOfSpecifier(specifier: string): string | undefined {
|
|
100
|
-
return packageNameFromSpecifier(specifier)
|
|
100
|
+
return packageNameFromSpecifier(specifier)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
export function packageNameForFile(file: string): string | undefined {
|
|
104
|
-
const packageRoot = nearestPackageRoot(path.dirname(file))
|
|
105
|
-
return packageRoot ? readPackageJson(packageRoot).name : undefined
|
|
104
|
+
const packageRoot = nearestPackageRoot(path.dirname(file))
|
|
105
|
+
return packageRoot ? readPackageJson(packageRoot).name : undefined
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
export function externalPackageImportTarget(
|
|
@@ -110,43 +110,47 @@ export function externalPackageImportTarget(
|
|
|
110
110
|
fromFile: string,
|
|
111
111
|
specifier: string,
|
|
112
112
|
): string | undefined {
|
|
113
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
114
|
-
if (!packageName) return undefined
|
|
115
|
-
const policy = getExternalPackagePolicy()
|
|
116
|
-
if (!policy.external(packageName) || policy.esmExternals() !== true) return undefined
|
|
117
|
-
const imported = resolvePackageSpecifier(root, fromFile, specifier, ['import', 'node', 'default'])
|
|
118
|
-
if (!imported || isEsmModuleFile(imported)) return undefined
|
|
119
|
-
const required = resolvePackageSpecifier(root, fromFile, specifier, [
|
|
120
|
-
|
|
113
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
114
|
+
if (!packageName) return undefined
|
|
115
|
+
const policy = getExternalPackagePolicy()
|
|
116
|
+
if (!policy.external(packageName) || policy.esmExternals() !== true) return undefined
|
|
117
|
+
const imported = resolvePackageSpecifier(root, fromFile, specifier, ['import', 'node', 'default'])
|
|
118
|
+
if (!imported || isEsmModuleFile(imported)) return undefined
|
|
119
|
+
const required = resolvePackageSpecifier(root, fromFile, specifier, [
|
|
120
|
+
'require',
|
|
121
|
+
'node',
|
|
122
|
+
'default',
|
|
123
|
+
])
|
|
124
|
+
return required && required !== imported ? required : undefined
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
interface TsConfig {
|
|
124
128
|
compilerOptions?: {
|
|
125
|
-
baseUrl?: string
|
|
126
|
-
paths?: Record<string, string[]
|
|
127
|
-
}
|
|
129
|
+
baseUrl?: string
|
|
130
|
+
paths?: Record<string, string[]>
|
|
131
|
+
}
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
export function setTsConfigPath(file: string | undefined): void {
|
|
131
|
-
setEngineTsConfigPath(file)
|
|
132
|
-
tsConfigCache.clear()
|
|
133
|
-
clearVendorPackageResolutions()
|
|
135
|
+
setEngineTsConfigPath(file)
|
|
136
|
+
tsConfigCache.clear()
|
|
137
|
+
clearVendorPackageResolutions()
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
interface PackageJson {
|
|
137
|
-
name?: string
|
|
138
|
-
type?: string
|
|
139
|
-
browser?: string
|
|
140
|
-
main?: string
|
|
141
|
-
module?: string
|
|
142
|
-
source?: string
|
|
143
|
-
exports?: PackageExport
|
|
144
|
-
imports?: Record<string, PackageExport
|
|
145
|
-
dependencies?: Record<string, string
|
|
146
|
-
devDependencies?: Record<string, string
|
|
147
|
-
optionalDependencies?: Record<string, string
|
|
148
|
-
peerDependencies?: Record<string, string
|
|
149
|
-
workspaces?: string[] | { packages?: string[] }
|
|
141
|
+
name?: string
|
|
142
|
+
type?: string
|
|
143
|
+
browser?: string
|
|
144
|
+
main?: string
|
|
145
|
+
module?: string
|
|
146
|
+
source?: string
|
|
147
|
+
exports?: PackageExport
|
|
148
|
+
imports?: Record<string, PackageExport>
|
|
149
|
+
dependencies?: Record<string, string>
|
|
150
|
+
devDependencies?: Record<string, string>
|
|
151
|
+
optionalDependencies?: Record<string, string>
|
|
152
|
+
peerDependencies?: Record<string, string>
|
|
153
|
+
workspaces?: string[] | { packages?: string[] }
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
// Compat (or any bundler extension) registers its bare-specifier to file aliases here (e.g. `next/form` ->
|
|
@@ -157,22 +161,22 @@ interface PackageJson {
|
|
|
157
161
|
// Deliberately NOT folded into resolveImport itself: that function has many callers, most of which treat
|
|
158
162
|
// "resolves to a real file" as "is a local, in-root source file", and an alias pointing outside the app root
|
|
159
163
|
// would misfire those assumptions. Only the route scanner's own walk needs this fallback.
|
|
160
|
-
let extraModuleAliases: Record<string, string> | undefined
|
|
164
|
+
let extraModuleAliases: Record<string, string> | undefined
|
|
161
165
|
// Compat registers these alongside the extension host, so they clear with it.
|
|
162
166
|
onExtensionHostReset(() => {
|
|
163
|
-
extraModuleAliases = undefined
|
|
164
|
-
clearVendorPackageResolutions()
|
|
165
|
-
})
|
|
167
|
+
extraModuleAliases = undefined
|
|
168
|
+
clearVendorPackageResolutions()
|
|
169
|
+
})
|
|
166
170
|
|
|
167
171
|
/** Register extra bare-specifier -> absolute-file aliases for the route scanner. */
|
|
168
172
|
export function setModuleAliases(aliases: Record<string, string> | undefined): void {
|
|
169
|
-
extraModuleAliases = aliases
|
|
173
|
+
extraModuleAliases = aliases
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
/** Bare-specifier alias lookup registered via setModuleAliases, if any. */
|
|
173
177
|
export function resolveModuleAlias(specifier: string): string | undefined {
|
|
174
|
-
const aliased = extraModuleAliases?.[specifier]
|
|
175
|
-
return aliased ? probeFile(aliased, localConditions) : undefined
|
|
178
|
+
const aliased = extraModuleAliases?.[specifier]
|
|
179
|
+
return aliased ? probeFile(aliased, localConditions) : undefined
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
/**
|
|
@@ -184,52 +188,52 @@ export function resolveImport(root: string, fromFile: string, specifier: string)
|
|
|
184
188
|
// rules, `.wasm?module`): those plugins strip the suffix and resolve the base
|
|
185
189
|
// themselves, and the query is part of the module's identity — so it is never
|
|
186
190
|
// a local resolution here, and the specifier reaches them untouched.
|
|
187
|
-
if (splitResourceQuery(specifier).query) return undefined
|
|
191
|
+
if (splitResourceQuery(specifier).query) return undefined
|
|
188
192
|
|
|
189
193
|
// realpath: a resolution reached through a symlinked shim dir (pages-compat)
|
|
190
194
|
// must collapse to the real app file, or downstream workspace-membership
|
|
191
195
|
// checks misclassify it as external and leave the specifier verbatim.
|
|
192
196
|
if (specifier.startsWith('.')) {
|
|
193
|
-
return resolveLocalFile(path.dirname(realImportPath(fromFile)), specifier)
|
|
197
|
+
return resolveLocalFile(path.dirname(realImportPath(fromFile)), specifier)
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
if (path.isAbsolute(specifier)) return probeFile(specifier, localConditions)
|
|
200
|
+
if (path.isAbsolute(specifier)) return probeFile(specifier, localConditions)
|
|
197
201
|
|
|
198
|
-
const resolutionRoot = resolutionRootForFile(root, fromFile)
|
|
202
|
+
const resolutionRoot = resolutionRootForFile(root, fromFile)
|
|
199
203
|
|
|
200
|
-
const tsResolved = resolveTsPath(resolutionRoot, specifier)
|
|
201
|
-
if (tsResolved) return realImportPath(tsResolved)
|
|
204
|
+
const tsResolved = resolveTsPath(resolutionRoot, specifier)
|
|
205
|
+
if (tsResolved) return realImportPath(tsResolved)
|
|
202
206
|
|
|
203
207
|
if (specifier.startsWith('#')) {
|
|
204
|
-
const resolved = resolveLocalFile(resolutionRoot, specifier)
|
|
205
|
-
return resolved ? realImportPath(resolved) : undefined
|
|
208
|
+
const resolved = resolveLocalFile(resolutionRoot, specifier)
|
|
209
|
+
return resolved ? realImportPath(resolved) : undefined
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
const workspaceResolved = resolveWorkspacePackageImport(root, specifier)
|
|
209
|
-
if (workspaceResolved) return workspaceResolved
|
|
212
|
+
const workspaceResolved = resolveWorkspacePackageImport(root, specifier)
|
|
213
|
+
if (workspaceResolved) return workspaceResolved
|
|
210
214
|
|
|
211
|
-
return resolveAppTreePackage(resolutionRoot, root, fromFile, specifier)
|
|
215
|
+
return resolveAppTreePackage(resolutionRoot, root, fromFile, specifier)
|
|
212
216
|
}
|
|
213
217
|
|
|
214
218
|
function resolveLocalFile(dir: string, specifier: string) {
|
|
215
|
-
const outcome = resolveFrom(dir, specifier, localConditions)
|
|
216
|
-
return outcome && 'path' in outcome ? outcome.path : undefined
|
|
219
|
+
const outcome = resolveFrom(dir, specifier, localConditions)
|
|
220
|
+
return outcome && 'path' in outcome ? outcome.path : undefined
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
// Every specifier of a file re-resolves that file's real path - one syscall per import, now one per
|
|
220
224
|
// path. Only successes are cached: a path that does not exist yet may resolve differently once the
|
|
221
225
|
// watcher creates it.
|
|
222
|
-
const realImportPathCache = new Map<string, string>()
|
|
226
|
+
const realImportPathCache = new Map<string, string>()
|
|
223
227
|
|
|
224
228
|
function realImportPath(file: string) {
|
|
225
|
-
const cached = realImportPathCache.get(file)
|
|
226
|
-
if (cached !== undefined) return cached
|
|
229
|
+
const cached = realImportPathCache.get(file)
|
|
230
|
+
if (cached !== undefined) return cached
|
|
227
231
|
try {
|
|
228
|
-
const real = realpathSync(file)
|
|
229
|
-
realImportPathCache.set(file, real)
|
|
230
|
-
return real
|
|
232
|
+
const real = realpathSync(file)
|
|
233
|
+
realImportPathCache.set(file, real)
|
|
234
|
+
return real
|
|
231
235
|
} catch {
|
|
232
|
-
return file
|
|
236
|
+
return file
|
|
233
237
|
}
|
|
234
238
|
}
|
|
235
239
|
|
|
@@ -238,10 +242,10 @@ function realImportPath(file: string) {
|
|
|
238
242
|
// at runtime. One resolution per (root, directory, specifier) instead of one per import of it: every module
|
|
239
243
|
// of a route's bundle asks about the same handful of app-tree packages, and each ask is a full oxc resolve.
|
|
240
244
|
// Successes only, exactly as `realImportPath` and `resolveRuntimeSpecifier` do.
|
|
241
|
-
const appTreeResolveCache = new Map<string, string>()
|
|
245
|
+
const appTreeResolveCache = new Map<string, string>()
|
|
242
246
|
// Bisect seam: `PNEXT_RESOLVE_APPTREE_MEMO=0` restores the resolve-per-import path.
|
|
243
247
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
244
|
-
const memoAppTree = process.env.PNEXT_RESOLVE_APPTREE_MEMO !== '0'
|
|
248
|
+
const memoAppTree = process.env.PNEXT_RESOLVE_APPTREE_MEMO !== '0'
|
|
245
249
|
|
|
246
250
|
function resolveAppTreePackage(
|
|
247
251
|
resolutionRoot: string,
|
|
@@ -249,24 +253,24 @@ function resolveAppTreePackage(
|
|
|
249
253
|
fromFile: string,
|
|
250
254
|
specifier: string,
|
|
251
255
|
) {
|
|
252
|
-
const from = path.dirname(path.resolve(fromFile))
|
|
253
|
-
const key = `${resolutionRoot}\0${root}\0${from}\0${specifier}
|
|
256
|
+
const from = path.dirname(path.resolve(fromFile))
|
|
257
|
+
const key = `${resolutionRoot}\0${root}\0${from}\0${specifier}`
|
|
254
258
|
if (memoAppTree) {
|
|
255
|
-
const cached = appTreeResolveCache.get(key)
|
|
256
|
-
if (cached !== undefined) return cached
|
|
259
|
+
const cached = appTreeResolveCache.get(key)
|
|
260
|
+
if (cached !== undefined) return cached
|
|
257
261
|
}
|
|
258
|
-
const outcome = resolveFrom(from, specifier, localConditions, resolutionRoot)
|
|
259
|
-
if (!outcome || !('path' in outcome)) return undefined
|
|
260
|
-
const resolved = isAppTreeFile(path.resolve(root), outcome.path) ? outcome.path : undefined
|
|
261
|
-
if (memoAppTree && resolved !== undefined) appTreeResolveCache.set(key, resolved)
|
|
262
|
-
return resolved
|
|
262
|
+
const outcome = resolveFrom(from, specifier, localConditions, resolutionRoot)
|
|
263
|
+
if (!outcome || !('path' in outcome)) return undefined
|
|
264
|
+
const resolved = isAppTreeFile(path.resolve(root), outcome.path) ? outcome.path : undefined
|
|
265
|
+
if (memoAppTree && resolved !== undefined) appTreeResolveCache.set(key, resolved)
|
|
266
|
+
return resolved
|
|
263
267
|
}
|
|
264
268
|
|
|
265
269
|
function isAppTreeFile(root: string, file: string) {
|
|
266
|
-
const relative = path.relative(root, file)
|
|
267
|
-
if (relative.startsWith('..') || path.isAbsolute(relative)) return false
|
|
268
|
-
const nodeModules = relative.split(path.sep).indexOf('node_modules')
|
|
269
|
-
return nodeModules !== 0
|
|
270
|
+
const relative = path.relative(root, file)
|
|
271
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) return false
|
|
272
|
+
const nodeModules = relative.split(path.sep).indexOf('node_modules')
|
|
273
|
+
return nodeModules !== 0
|
|
270
274
|
}
|
|
271
275
|
|
|
272
276
|
/**
|
|
@@ -281,9 +285,9 @@ export function resolveConfiguredTsPath(
|
|
|
281
285
|
specifier: string,
|
|
282
286
|
): string | undefined {
|
|
283
287
|
if (specifier.startsWith('.') || specifier.startsWith('#') || path.isAbsolute(specifier)) {
|
|
284
|
-
return undefined
|
|
288
|
+
return undefined
|
|
285
289
|
}
|
|
286
|
-
return resolveTsPath(resolutionRootForFile(root, fromFile), specifier)
|
|
290
|
+
return resolveTsPath(resolutionRootForFile(root, fromFile), specifier)
|
|
287
291
|
}
|
|
288
292
|
|
|
289
293
|
/**
|
|
@@ -293,38 +297,41 @@ export function resolveConfiguredTsPath(
|
|
|
293
297
|
* root). Lets a caller pre-filter specifiers instead of asking per import.
|
|
294
298
|
*/
|
|
295
299
|
export function configuredTsPathPatterns(root: string, workspaceRoot?: string): string[] {
|
|
296
|
-
const roots = new Set([path.resolve(root)])
|
|
300
|
+
const roots = new Set([path.resolve(root)])
|
|
297
301
|
if (workspaceRoot) {
|
|
298
|
-
const resolved = path.resolve(workspaceRoot)
|
|
299
|
-
roots.add(resolved)
|
|
300
|
-
for (const packageRoot of workspacePackages(resolved).values()) roots.add(packageRoot)
|
|
302
|
+
const resolved = path.resolve(workspaceRoot)
|
|
303
|
+
roots.add(resolved)
|
|
304
|
+
for (const packageRoot of workspacePackages(resolved).values()) roots.add(packageRoot)
|
|
301
305
|
}
|
|
302
|
-
const patterns = new Set<string>()
|
|
306
|
+
const patterns = new Set<string>()
|
|
303
307
|
for (const dir of roots) {
|
|
304
308
|
for (const pattern of Object.keys(readTsConfig(dir).compilerOptions?.paths ?? {})) {
|
|
305
|
-
patterns.add(pattern)
|
|
309
|
+
patterns.add(pattern)
|
|
306
310
|
}
|
|
307
311
|
}
|
|
308
|
-
return [...patterns]
|
|
312
|
+
return [...patterns]
|
|
309
313
|
}
|
|
310
314
|
|
|
311
315
|
function resolveTsPath(root: string, specifier: string) {
|
|
312
|
-
const compilerOptions = readTsConfig(root).compilerOptions ?? {}
|
|
313
|
-
const baseUrl = path.resolve(root, compilerOptions.baseUrl ?? '.')
|
|
316
|
+
const compilerOptions = readTsConfig(root).compilerOptions ?? {}
|
|
317
|
+
const baseUrl = path.resolve(root, compilerOptions.baseUrl ?? '.')
|
|
314
318
|
|
|
315
319
|
for (const [pattern, targets] of Object.entries(compilerOptions.paths ?? {})) {
|
|
316
|
-
const match = matchPattern(pattern, specifier)
|
|
317
|
-
if (!match) continue
|
|
320
|
+
const match = matchPattern(pattern, specifier)
|
|
321
|
+
if (!match) continue
|
|
318
322
|
for (const target of targets) {
|
|
319
|
-
const resolved = probeFile(
|
|
320
|
-
|
|
323
|
+
const resolved = probeFile(
|
|
324
|
+
path.resolve(baseUrl, applyPattern(target, match)),
|
|
325
|
+
localConditions,
|
|
326
|
+
)
|
|
327
|
+
if (resolved) return resolved
|
|
321
328
|
}
|
|
322
329
|
}
|
|
323
330
|
|
|
324
|
-
return undefined
|
|
331
|
+
return undefined
|
|
325
332
|
}
|
|
326
333
|
|
|
327
|
-
type PackageExport = unknown
|
|
334
|
+
type PackageExport = unknown
|
|
328
335
|
|
|
329
336
|
/**
|
|
330
337
|
* Resolve a sibling workspace package to its RAW first-party source - the `source`/`src` entries and the
|
|
@@ -332,47 +339,53 @@ type PackageExport = unknown;
|
|
|
332
339
|
* that does not exist in a checkout.
|
|
333
340
|
*/
|
|
334
341
|
function resolveWorkspacePackageImport(root: string, specifier: string) {
|
|
335
|
-
const workspaceRoot = findWorkspaceRoot(root)
|
|
336
|
-
if (!workspaceRoot) return undefined
|
|
342
|
+
const workspaceRoot = findWorkspaceRoot(root)
|
|
343
|
+
if (!workspaceRoot) return undefined
|
|
337
344
|
|
|
338
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
339
|
-
if (!packageName) return undefined
|
|
345
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
346
|
+
if (!packageName) return undefined
|
|
340
347
|
|
|
341
|
-
const packageRoot = workspacePackages(workspaceRoot).get(packageName)
|
|
342
|
-
if (!packageRoot) return undefined
|
|
348
|
+
const packageRoot = workspacePackages(workspaceRoot).get(packageName)
|
|
349
|
+
if (!packageRoot) return undefined
|
|
343
350
|
|
|
344
|
-
const packageJson = readPackageJson(packageRoot)
|
|
345
|
-
const subpath = subpathOfSpecifier(packageName, specifier)
|
|
346
|
-
const exported = packageExportTarget(packageJson.exports, subpath)
|
|
351
|
+
const packageJson = readPackageJson(packageRoot)
|
|
352
|
+
const subpath = subpathOfSpecifier(packageName, specifier)
|
|
353
|
+
const exported = packageExportTarget(packageJson.exports, subpath)
|
|
347
354
|
if (exported) {
|
|
348
|
-
const resolved = probePackageTarget(path.resolve(packageRoot, exported), localConditions)
|
|
349
|
-
if (resolved && isInside(packageRoot, resolved)) return resolved
|
|
355
|
+
const resolved = probePackageTarget(path.resolve(packageRoot, exported), localConditions)
|
|
356
|
+
if (resolved && isInside(packageRoot, resolved)) return resolved
|
|
350
357
|
}
|
|
351
358
|
|
|
352
|
-
const onDisk = onDiskSubpath(packageRoot, subpath, localConditions)
|
|
353
|
-
if (onDisk) return onDisk
|
|
354
|
-
|
|
355
|
-
for (const entry of [
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
+
const onDisk = onDiskSubpath(packageRoot, subpath, localConditions)
|
|
360
|
+
if (onDisk) return onDisk
|
|
361
|
+
|
|
362
|
+
for (const entry of [
|
|
363
|
+
packageJson.source,
|
|
364
|
+
packageJson.module,
|
|
365
|
+
packageJson.main,
|
|
366
|
+
'./src/index',
|
|
367
|
+
'./index',
|
|
368
|
+
]) {
|
|
369
|
+
if (!entry) continue
|
|
370
|
+
const resolved = probePackageTarget(path.resolve(packageRoot, entry), localConditions)
|
|
371
|
+
if (resolved) return resolved
|
|
359
372
|
}
|
|
360
373
|
|
|
361
|
-
return undefined
|
|
374
|
+
return undefined
|
|
362
375
|
}
|
|
363
376
|
|
|
364
377
|
function packageExportTarget(exports: PackageJson['exports'], subpath: string) {
|
|
365
|
-
if (!exports) return undefined
|
|
366
|
-
if (!isSubpathExports(exports)) return subpath === '.' ? packageTargetPath(exports) : undefined
|
|
378
|
+
if (!exports) return undefined
|
|
379
|
+
if (!isSubpathExports(exports)) return subpath === '.' ? packageTargetPath(exports) : undefined
|
|
367
380
|
|
|
368
381
|
for (const [pattern, target] of Object.entries(exports)) {
|
|
369
|
-
const match = matchPattern(pattern, subpath)
|
|
370
|
-
if (!match) continue
|
|
371
|
-
const targetPath = packageTargetPath(target)
|
|
372
|
-
if (targetPath) return applyPattern(targetPath, match)
|
|
382
|
+
const match = matchPattern(pattern, subpath)
|
|
383
|
+
if (!match) continue
|
|
384
|
+
const targetPath = packageTargetPath(target)
|
|
385
|
+
if (targetPath) return applyPattern(targetPath, match)
|
|
373
386
|
}
|
|
374
387
|
|
|
375
|
-
return undefined
|
|
388
|
+
return undefined
|
|
376
389
|
}
|
|
377
390
|
|
|
378
391
|
function packageExportTargetForConditions(
|
|
@@ -380,102 +393,102 @@ function packageExportTargetForConditions(
|
|
|
380
393
|
subpath: string,
|
|
381
394
|
conditions: readonly string[],
|
|
382
395
|
): string | undefined {
|
|
383
|
-
if (!exports) return undefined
|
|
396
|
+
if (!exports) return undefined
|
|
384
397
|
if (!isSubpathExports(exports)) {
|
|
385
|
-
return subpath === '.' ? packageTargetPathForConditions(exports, conditions) : undefined
|
|
398
|
+
return subpath === '.' ? packageTargetPathForConditions(exports, conditions) : undefined
|
|
386
399
|
}
|
|
387
400
|
|
|
388
401
|
for (const [pattern, target] of Object.entries(exports)) {
|
|
389
|
-
const match = matchPattern(pattern, subpath)
|
|
390
|
-
if (!match) continue
|
|
391
|
-
const targetPath = packageTargetPathForConditions(target, conditions)
|
|
392
|
-
if (targetPath) return applyPattern(targetPath, match)
|
|
402
|
+
const match = matchPattern(pattern, subpath)
|
|
403
|
+
if (!match) continue
|
|
404
|
+
const targetPath = packageTargetPathForConditions(target, conditions)
|
|
405
|
+
if (targetPath) return applyPattern(targetPath, match)
|
|
393
406
|
}
|
|
394
407
|
|
|
395
|
-
return undefined
|
|
408
|
+
return undefined
|
|
396
409
|
}
|
|
397
410
|
|
|
398
411
|
function packageTargetPathForConditions(
|
|
399
412
|
target: unknown,
|
|
400
413
|
conditions: readonly string[],
|
|
401
414
|
): string | undefined {
|
|
402
|
-
if (!target) return undefined
|
|
403
|
-
if (typeof target === 'string') return target
|
|
415
|
+
if (!target) return undefined
|
|
416
|
+
if (typeof target === 'string') return target
|
|
404
417
|
if (Array.isArray(target)) {
|
|
405
418
|
for (const item of target) {
|
|
406
|
-
const resolved = packageTargetPathForConditions(item, conditions)
|
|
407
|
-
if (resolved) return resolved
|
|
419
|
+
const resolved = packageTargetPathForConditions(item, conditions)
|
|
420
|
+
if (resolved) return resolved
|
|
408
421
|
}
|
|
409
|
-
return undefined
|
|
422
|
+
return undefined
|
|
410
423
|
}
|
|
411
424
|
|
|
412
|
-
if (!isPackageExportObject(target)) return undefined
|
|
425
|
+
if (!isPackageExportObject(target)) return undefined
|
|
413
426
|
|
|
414
427
|
for (const [key, value] of Object.entries(target)) {
|
|
415
|
-
if (key !== 'default' && !conditions.includes(key)) continue
|
|
416
|
-
const resolved = packageTargetPathForConditions(value, conditions)
|
|
417
|
-
if (resolved) return resolved
|
|
428
|
+
if (key !== 'default' && !conditions.includes(key)) continue
|
|
429
|
+
const resolved = packageTargetPathForConditions(value, conditions)
|
|
430
|
+
if (resolved) return resolved
|
|
418
431
|
}
|
|
419
432
|
|
|
420
|
-
return undefined
|
|
433
|
+
return undefined
|
|
421
434
|
}
|
|
422
435
|
|
|
423
436
|
function isSubpathExports(exports: PackageExport): exports is Record<string, unknown> {
|
|
424
|
-
return isPackageExportObject(exports) && Object.keys(exports).some(key => key.startsWith('.'))
|
|
437
|
+
return isPackageExportObject(exports) && Object.keys(exports).some(key => key.startsWith('.'))
|
|
425
438
|
}
|
|
426
439
|
|
|
427
440
|
function packageTargetPath(target: unknown): string | undefined {
|
|
428
|
-
if (!target) return undefined
|
|
429
|
-
if (typeof target === 'string') return target
|
|
441
|
+
if (!target) return undefined
|
|
442
|
+
if (typeof target === 'string') return target
|
|
430
443
|
if (Array.isArray(target)) {
|
|
431
444
|
for (const item of target) {
|
|
432
|
-
const resolved = packageTargetPath(item)
|
|
433
|
-
if (resolved) return resolved
|
|
445
|
+
const resolved = packageTargetPath(item)
|
|
446
|
+
if (resolved) return resolved
|
|
434
447
|
}
|
|
435
|
-
return undefined
|
|
448
|
+
return undefined
|
|
436
449
|
}
|
|
437
450
|
|
|
438
|
-
if (!isPackageExportObject(target)) return undefined
|
|
451
|
+
if (!isPackageExportObject(target)) return undefined
|
|
439
452
|
|
|
440
453
|
for (const key of ['source', 'import', 'browser', 'node', 'default', 'types', 'require']) {
|
|
441
|
-
const resolved = packageTargetPath(target[key])
|
|
442
|
-
if (resolved) return resolved
|
|
454
|
+
const resolved = packageTargetPath(target[key])
|
|
455
|
+
if (resolved) return resolved
|
|
443
456
|
}
|
|
444
457
|
|
|
445
458
|
for (const value of Object.values(target)) {
|
|
446
|
-
const resolved = packageTargetPath(value)
|
|
447
|
-
if (resolved) return resolved
|
|
459
|
+
const resolved = packageTargetPath(value)
|
|
460
|
+
if (resolved) return resolved
|
|
448
461
|
}
|
|
449
462
|
|
|
450
|
-
return undefined
|
|
463
|
+
return undefined
|
|
451
464
|
}
|
|
452
465
|
|
|
453
466
|
function isPackageExportObject(target: unknown): target is Record<string, unknown> {
|
|
454
|
-
return typeof target === 'object' && target !== null && !Array.isArray(target)
|
|
467
|
+
return typeof target === 'object' && target !== null && !Array.isArray(target)
|
|
455
468
|
}
|
|
456
469
|
|
|
457
470
|
function matchPattern(pattern: string, specifier: string) {
|
|
458
|
-
if (pattern === specifier) return { wildcard: '' }
|
|
459
|
-
const star = pattern.indexOf('*')
|
|
460
|
-
if (star === -1) return undefined
|
|
461
|
-
const prefix = pattern.slice(0, star)
|
|
462
|
-
const suffix = pattern.slice(star + 1)
|
|
463
|
-
if (!specifier.startsWith(prefix) || !specifier.endsWith(suffix)) return undefined
|
|
464
|
-
return { wildcard: specifier.slice(prefix.length, specifier.length - suffix.length) }
|
|
471
|
+
if (pattern === specifier) return { wildcard: '' }
|
|
472
|
+
const star = pattern.indexOf('*')
|
|
473
|
+
if (star === -1) return undefined
|
|
474
|
+
const prefix = pattern.slice(0, star)
|
|
475
|
+
const suffix = pattern.slice(star + 1)
|
|
476
|
+
if (!specifier.startsWith(prefix) || !specifier.endsWith(suffix)) return undefined
|
|
477
|
+
return { wildcard: specifier.slice(prefix.length, specifier.length - suffix.length) }
|
|
465
478
|
}
|
|
466
479
|
|
|
467
480
|
function applyPattern(pattern: string, match: { wildcard: string }) {
|
|
468
|
-
return pattern.replace('*', match.wildcard)
|
|
481
|
+
return pattern.replace('*', match.wildcard)
|
|
469
482
|
}
|
|
470
483
|
|
|
471
484
|
function packageNameFromSpecifier(specifier: string) {
|
|
472
|
-
const parts = specifier.split('/')
|
|
473
|
-
if (specifier.startsWith('@')) return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : undefined
|
|
474
|
-
return parts[0] || undefined
|
|
485
|
+
const parts = specifier.split('/')
|
|
486
|
+
if (specifier.startsWith('@')) return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : undefined
|
|
487
|
+
return parts[0] || undefined
|
|
475
488
|
}
|
|
476
489
|
|
|
477
490
|
function subpathOfSpecifier(packageName: string, specifier: string) {
|
|
478
|
-
return specifier === packageName ? '.' : `.${specifier.slice(packageName.length)}
|
|
491
|
+
return specifier === packageName ? '.' : `.${specifier.slice(packageName.length)}`
|
|
479
492
|
}
|
|
480
493
|
|
|
481
494
|
/**
|
|
@@ -483,10 +496,10 @@ function subpathOfSpecifier(packageName: string, specifier: string) {
|
|
|
483
496
|
* repeat resolutions on exactly the inputs the resolver reads.
|
|
484
497
|
*/
|
|
485
498
|
export function resolutionRootForFile(root: string, fromFile: string) {
|
|
486
|
-
const resolvedRoot = path.resolve(root)
|
|
487
|
-
const resolvedFile = path.resolve(fromFile)
|
|
488
|
-
if (isInside(resolvedRoot, resolvedFile)) return resolvedRoot
|
|
489
|
-
return nearestPackageRoot(path.dirname(resolvedFile)) ?? resolvedRoot
|
|
499
|
+
const resolvedRoot = path.resolve(root)
|
|
500
|
+
const resolvedFile = path.resolve(fromFile)
|
|
501
|
+
if (isInside(resolvedRoot, resolvedFile)) return resolvedRoot
|
|
502
|
+
return nearestPackageRoot(path.dirname(resolvedFile)) ?? resolvedRoot
|
|
490
503
|
}
|
|
491
504
|
|
|
492
505
|
/**
|
|
@@ -501,10 +514,10 @@ export function resolveNestedPackageFromImporter(
|
|
|
501
514
|
specifier: string,
|
|
502
515
|
conditions: readonly string[],
|
|
503
516
|
): string | undefined {
|
|
504
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
505
|
-
if (!packageName) return undefined
|
|
506
|
-
const from = path.dirname(realImportPath(path.resolve(importerFile)))
|
|
507
|
-
return realLinkedPackageFile(resolvePackageFrom(from, packageName, specifier, conditions))
|
|
517
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
518
|
+
if (!packageName) return undefined
|
|
519
|
+
const from = path.dirname(realImportPath(path.resolve(importerFile)))
|
|
520
|
+
return realLinkedPackageFile(resolvePackageFrom(from, packageName, specifier, conditions))
|
|
508
521
|
}
|
|
509
522
|
|
|
510
523
|
/**
|
|
@@ -512,46 +525,46 @@ export function resolveNestedPackageFromImporter(
|
|
|
512
525
|
* resolve, every `isEsmModuleFile` and every vendor build asks it about the
|
|
513
526
|
* same few thousand node_modules directories.
|
|
514
527
|
*/
|
|
515
|
-
const packageRoots = new Map<string, string | undefined>()
|
|
528
|
+
const packageRoots = new Map<string, string | undefined>()
|
|
516
529
|
|
|
517
530
|
function nearestPackageRoot(fromDir: string) {
|
|
518
|
-
const start = path.resolve(fromDir)
|
|
519
|
-
if (packageRoots.has(start)) return packageRoots.get(start)
|
|
520
|
-
let dir = start
|
|
521
|
-
const walked: string[] = []
|
|
522
|
-
let found: string | undefined
|
|
531
|
+
const start = path.resolve(fromDir)
|
|
532
|
+
if (packageRoots.has(start)) return packageRoots.get(start)
|
|
533
|
+
let dir = start
|
|
534
|
+
const walked: string[] = []
|
|
535
|
+
let found: string | undefined
|
|
523
536
|
while (true) {
|
|
524
|
-
walked.push(dir)
|
|
537
|
+
walked.push(dir)
|
|
525
538
|
// Plain existsSync: the walk is memoized per dir, a dirent listing of large
|
|
526
539
|
// node_modules dirs costs more than the one probe it would save.
|
|
527
540
|
if (existsSync(path.join(dir, 'package.json'))) {
|
|
528
|
-
found = dir
|
|
529
|
-
break
|
|
541
|
+
found = dir
|
|
542
|
+
break
|
|
530
543
|
}
|
|
531
|
-
const parent = path.dirname(dir)
|
|
532
|
-
if (parent === dir) break
|
|
533
|
-
dir = parent
|
|
544
|
+
const parent = path.dirname(dir)
|
|
545
|
+
if (parent === dir) break
|
|
546
|
+
dir = parent
|
|
534
547
|
}
|
|
535
|
-
for (const seen of walked) packageRoots.set(seen, found)
|
|
536
|
-
return found
|
|
548
|
+
for (const seen of walked) packageRoots.set(seen, found)
|
|
549
|
+
return found
|
|
537
550
|
}
|
|
538
551
|
|
|
539
552
|
/**
|
|
540
553
|
* Entry resolutions the vendor build already computed, handed to the CJS-interop
|
|
541
554
|
* plugin so its entry-point onResolve never re-resolves a bare specifier.
|
|
542
555
|
*/
|
|
543
|
-
const vendorEntryProvisions = new Map<string, string>()
|
|
556
|
+
const vendorEntryProvisions = new Map<string, string>()
|
|
544
557
|
|
|
545
558
|
export function provideEntryResolution(specifier: string, resolveDir: string, resolved: string) {
|
|
546
|
-
vendorEntryProvisions.set(`${specifier}\0${resolveDir}`, resolved)
|
|
559
|
+
vendorEntryProvisions.set(`${specifier}\0${resolveDir}`, resolved)
|
|
547
560
|
}
|
|
548
561
|
|
|
549
562
|
export function clearProvidedEntryResolutions() {
|
|
550
|
-
vendorEntryProvisions.clear()
|
|
563
|
+
vendorEntryProvisions.clear()
|
|
551
564
|
}
|
|
552
565
|
|
|
553
566
|
export function providedEntryResolution(specifier: string, resolveDir: string) {
|
|
554
|
-
return vendorEntryProvisions.get(`${specifier}\0${resolveDir}`)
|
|
567
|
+
return vendorEntryProvisions.get(`${specifier}\0${resolveDir}`)
|
|
555
568
|
}
|
|
556
569
|
|
|
557
570
|
export function resolvePackageSpecifier(
|
|
@@ -560,10 +573,10 @@ export function resolvePackageSpecifier(
|
|
|
560
573
|
specifier: string,
|
|
561
574
|
conditions: readonly string[],
|
|
562
575
|
): string | undefined {
|
|
563
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
564
|
-
if (!packageName) return undefined
|
|
565
|
-
const from = resolutionRootForFile(root, fromFile)
|
|
566
|
-
return realLinkedPackageFile(resolvePackageFrom(from, packageName, specifier, conditions))
|
|
576
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
577
|
+
if (!packageName) return undefined
|
|
578
|
+
const from = resolutionRootForFile(root, fromFile)
|
|
579
|
+
return realLinkedPackageFile(resolvePackageFrom(from, packageName, specifier, conditions))
|
|
567
580
|
}
|
|
568
581
|
|
|
569
582
|
/**
|
|
@@ -572,7 +585,7 @@ export function resolvePackageSpecifier(
|
|
|
572
585
|
* artifact cache and the plugin source memo both assume it) - the ordinary dev resolver keeps
|
|
573
586
|
* resolving live.
|
|
574
587
|
*/
|
|
575
|
-
const vendorPackageResolutions = new Map<string, string | undefined>()
|
|
588
|
+
const vendorPackageResolutions = new Map<string, string | undefined>()
|
|
576
589
|
|
|
577
590
|
export function resolveVendorPackageSpecifier(
|
|
578
591
|
root: string,
|
|
@@ -580,21 +593,23 @@ export function resolveVendorPackageSpecifier(
|
|
|
580
593
|
specifier: string,
|
|
581
594
|
conditions: readonly string[],
|
|
582
595
|
): string | undefined {
|
|
583
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
584
|
-
if (!packageName) return undefined
|
|
596
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
597
|
+
if (!packageName) return undefined
|
|
585
598
|
// Keyed on the RESOLUTION ROOT, not the importer's directory: that is the only thing the resolver
|
|
586
599
|
// reads out of `fromFile`, and one root stands in for the hundreds of importer dirs inside it.
|
|
587
600
|
// Keying on `fromFile` left the memo missing on nearly every call.
|
|
588
|
-
const from = resolutionRootForFile(root, fromFile)
|
|
589
|
-
const key = `${from}\0${specifier}\0${conditions.join(',')}
|
|
590
|
-
if (vendorPackageResolutions.has(key)) return vendorPackageResolutions.get(key)
|
|
591
|
-
const resolved = realLinkedPackageFile(
|
|
592
|
-
|
|
593
|
-
|
|
601
|
+
const from = resolutionRootForFile(root, fromFile)
|
|
602
|
+
const key = `${from}\0${specifier}\0${conditions.join(',')}`
|
|
603
|
+
if (vendorPackageResolutions.has(key)) return vendorPackageResolutions.get(key)
|
|
604
|
+
const resolved = realLinkedPackageFile(
|
|
605
|
+
resolvePackageFrom(from, packageName, specifier, conditions),
|
|
606
|
+
)
|
|
607
|
+
vendorPackageResolutions.set(key, resolved)
|
|
608
|
+
return resolved
|
|
594
609
|
}
|
|
595
610
|
|
|
596
611
|
export function clearVendorPackageResolutions() {
|
|
597
|
-
vendorPackageResolutions.clear()
|
|
612
|
+
vendorPackageResolutions.clear()
|
|
598
613
|
}
|
|
599
614
|
|
|
600
615
|
/**
|
|
@@ -603,8 +618,8 @@ export function clearVendorPackageResolutions() {
|
|
|
603
618
|
* since the last resolve can move an answer this remembered.
|
|
604
619
|
*/
|
|
605
620
|
export function clearAppTreeResolutions() {
|
|
606
|
-
appTreeResolveCache.clear()
|
|
607
|
-
externalLoadTargets.clear()
|
|
621
|
+
appTreeResolveCache.clear()
|
|
622
|
+
externalLoadTargets.clear()
|
|
608
623
|
}
|
|
609
624
|
|
|
610
625
|
export function resolvePackageImportSpecifier(
|
|
@@ -613,10 +628,10 @@ export function resolvePackageImportSpecifier(
|
|
|
613
628
|
specifier: string,
|
|
614
629
|
conditions: readonly string[],
|
|
615
630
|
): string | undefined {
|
|
616
|
-
if (!specifier.startsWith('#')) return undefined
|
|
617
|
-
const from = nearestPackageRoot(path.dirname(fromFile)) ?? resolutionRootForFile(root, fromFile)
|
|
618
|
-
const outcome = resolveFrom(from, specifier, conditions)
|
|
619
|
-
return outcome && 'path' in outcome ? outcome.path : undefined
|
|
631
|
+
if (!specifier.startsWith('#')) return undefined
|
|
632
|
+
const from = nearestPackageRoot(path.dirname(fromFile)) ?? resolutionRootForFile(root, fromFile)
|
|
633
|
+
const outcome = resolveFrom(from, specifier, conditions)
|
|
634
|
+
return outcome && 'path' in outcome ? outcome.path : undefined
|
|
620
635
|
}
|
|
621
636
|
|
|
622
637
|
function resolvePackageFrom(
|
|
@@ -625,22 +640,22 @@ function resolvePackageFrom(
|
|
|
625
640
|
specifier: string,
|
|
626
641
|
conditions: readonly string[],
|
|
627
642
|
) {
|
|
628
|
-
const outcome = resolveFrom(from, specifier, conditions)
|
|
629
|
-
if (outcome && 'path' in outcome) return outcome.path
|
|
630
|
-
const packageRoot = findNodePackageRoot(from, packageName)
|
|
631
|
-
if (!packageRoot) return undefined
|
|
632
|
-
return onDiskSubpath(packageRoot, subpathOfSpecifier(packageName, specifier), conditions)
|
|
643
|
+
const outcome = resolveFrom(from, specifier, conditions)
|
|
644
|
+
if (outcome && 'path' in outcome) return outcome.path
|
|
645
|
+
const packageRoot = findNodePackageRoot(from, packageName)
|
|
646
|
+
if (!packageRoot) return undefined
|
|
647
|
+
return onDiskSubpath(packageRoot, subpathOfSpecifier(packageName, specifier), conditions)
|
|
633
648
|
}
|
|
634
649
|
|
|
635
650
|
// `exports` blocks deep access, so an on-disk file at the same path is not a
|
|
636
651
|
// fallback Node would ever take — but pnext's resolver does take it.
|
|
637
652
|
function onDiskSubpath(packageRoot: string, subpath: string, conditions: readonly string[]) {
|
|
638
|
-
if (subpath === '.') return undefined
|
|
639
|
-
const resolved = probePackageTarget(path.resolve(packageRoot, subpath.slice(2)), conditions)
|
|
640
|
-
return resolved && isInside(packageRoot, resolved) ? resolved : undefined
|
|
653
|
+
if (subpath === '.') return undefined
|
|
654
|
+
const resolved = probePackageTarget(path.resolve(packageRoot, subpath.slice(2)), conditions)
|
|
655
|
+
return resolved && isInside(packageRoot, resolved) ? resolved : undefined
|
|
641
656
|
}
|
|
642
657
|
|
|
643
|
-
const runtimeResolveCache = new Map<string, string>()
|
|
658
|
+
const runtimeResolveCache = new Map<string, string>()
|
|
644
659
|
|
|
645
660
|
/**
|
|
646
661
|
* Bun's own resolution of `specifier` from `dir`, memoized. Source rewrites ask this about a module they are
|
|
@@ -649,37 +664,37 @@ const runtimeResolveCache = new Map<string, string>();
|
|
|
649
664
|
* cached, as with `realImportPath`: a specifier the watcher is about to create must resolve on the next ask.
|
|
650
665
|
*/
|
|
651
666
|
export function resolveRuntimeSpecifier(dir: string, specifier: string): string | undefined {
|
|
652
|
-
const key = `${dir}\0${specifier}
|
|
653
|
-
const cached = runtimeResolveCache.get(key)
|
|
654
|
-
if (cached !== undefined) return cached
|
|
667
|
+
const key = `${dir}\0${specifier}`
|
|
668
|
+
const cached = runtimeResolveCache.get(key)
|
|
669
|
+
if (cached !== undefined) return cached
|
|
655
670
|
try {
|
|
656
|
-
const resolved = Bun.resolveSync(specifier, dir)
|
|
657
|
-
runtimeResolveCache.set(key, resolved)
|
|
658
|
-
return resolved
|
|
671
|
+
const resolved = Bun.resolveSync(specifier, dir)
|
|
672
|
+
runtimeResolveCache.set(key, resolved)
|
|
673
|
+
return resolved
|
|
659
674
|
} catch {
|
|
660
|
-
return undefined
|
|
675
|
+
return undefined
|
|
661
676
|
}
|
|
662
677
|
}
|
|
663
678
|
|
|
664
|
-
const linkedPackageFileCache = new Map<string, string>()
|
|
679
|
+
const linkedPackageFileCache = new Map<string, string>()
|
|
665
680
|
|
|
666
681
|
// webpack's `resolve.symlinks: true`: a linked workspace package compiles from
|
|
667
682
|
// its real path, as first-party source. Only collapse when the realpath escapes
|
|
668
683
|
// node_modules — pnpm's virtual store links within it, and those paths carry
|
|
669
684
|
// the version identity nested-dependency pinning needs.
|
|
670
685
|
function realLinkedPackageFile(file: string | undefined) {
|
|
671
|
-
if (!file) return file
|
|
672
|
-
const cached = linkedPackageFileCache.get(file)
|
|
673
|
-
if (cached !== undefined) return cached
|
|
674
|
-
let resolved = file
|
|
686
|
+
if (!file) return file
|
|
687
|
+
const cached = linkedPackageFileCache.get(file)
|
|
688
|
+
if (cached !== undefined) return cached
|
|
689
|
+
let resolved = file
|
|
675
690
|
try {
|
|
676
|
-
const real = realpathSync(file)
|
|
677
|
-
if (!real.includes(`${path.sep}node_modules${path.sep}`)) resolved = real
|
|
691
|
+
const real = realpathSync(file)
|
|
692
|
+
if (!real.includes(`${path.sep}node_modules${path.sep}`)) resolved = real
|
|
678
693
|
} catch {
|
|
679
694
|
/* keep the unresolved path */
|
|
680
695
|
}
|
|
681
|
-
linkedPackageFileCache.set(file, resolved)
|
|
682
|
-
return resolved
|
|
696
|
+
linkedPackageFileCache.set(file, resolved)
|
|
697
|
+
return resolved
|
|
683
698
|
}
|
|
684
699
|
|
|
685
700
|
/**
|
|
@@ -698,19 +713,19 @@ export function isPackageSubpathUnexported(
|
|
|
698
713
|
specifier: string,
|
|
699
714
|
conditions: readonly string[],
|
|
700
715
|
): boolean {
|
|
701
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
702
|
-
if (!packageName) return false
|
|
703
|
-
const resolutionRoot = resolutionRootForFile(root, fromFile)
|
|
716
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
717
|
+
if (!packageName) return false
|
|
718
|
+
const resolutionRoot = resolutionRootForFile(root, fromFile)
|
|
704
719
|
const packageRoot =
|
|
705
720
|
findNodePackageRoot(resolutionRoot, packageName) ??
|
|
706
|
-
findLinkedPackageRoot(resolutionRoot, packageName)
|
|
707
|
-
if (!packageRoot) return false
|
|
708
|
-
const { exports } = readPackageJson(packageRoot)
|
|
709
|
-
if (!exports || !isSubpathExports(exports)) return false
|
|
710
|
-
const subpath = subpathOfSpecifier(packageName, specifier)
|
|
711
|
-
if (!Object.keys(exports).some(pattern => matchPattern(pattern, subpath))) return false
|
|
712
|
-
if (packageExportTargetForConditions(exports, subpath, conditions)) return false
|
|
713
|
-
return !onDiskSubpath(packageRoot, subpath, conditions)
|
|
721
|
+
findLinkedPackageRoot(resolutionRoot, packageName)
|
|
722
|
+
if (!packageRoot) return false
|
|
723
|
+
const { exports } = readPackageJson(packageRoot)
|
|
724
|
+
if (!exports || !isSubpathExports(exports)) return false
|
|
725
|
+
const subpath = subpathOfSpecifier(packageName, specifier)
|
|
726
|
+
if (!Object.keys(exports).some(pattern => matchPattern(pattern, subpath))) return false
|
|
727
|
+
if (packageExportTargetForConditions(exports, subpath, conditions)) return false
|
|
728
|
+
return !onDiskSubpath(packageRoot, subpath, conditions)
|
|
714
729
|
}
|
|
715
730
|
|
|
716
731
|
/** Resolve a `link:`/`file:`/relative dependency to its checked-out source. */
|
|
@@ -720,114 +735,110 @@ export function resolveLinkedPackageSpecifier(
|
|
|
720
735
|
specifier: string,
|
|
721
736
|
conditions: readonly string[],
|
|
722
737
|
): string | undefined {
|
|
723
|
-
const packageName = packageNameFromSpecifier(specifier)
|
|
724
|
-
if (!packageName) return undefined
|
|
725
|
-
const packageRoot = findLinkedPackageRoot(resolutionRootForFile(root, fromFile), packageName)
|
|
726
|
-
if (!packageRoot) return undefined
|
|
738
|
+
const packageName = packageNameFromSpecifier(specifier)
|
|
739
|
+
if (!packageName) return undefined
|
|
740
|
+
const packageRoot = findLinkedPackageRoot(resolutionRootForFile(root, fromFile), packageName)
|
|
741
|
+
if (!packageRoot) return undefined
|
|
727
742
|
return realLinkedPackageFile(
|
|
728
743
|
resolvePackageAtRoot(packageRoot, subpathOfSpecifier(packageName, specifier), conditions),
|
|
729
|
-
)
|
|
744
|
+
)
|
|
730
745
|
}
|
|
731
746
|
|
|
732
|
-
function resolvePackageAtRoot(
|
|
733
|
-
packageRoot
|
|
734
|
-
subpath
|
|
735
|
-
conditions: readonly string[],
|
|
736
|
-
) {
|
|
737
|
-
const packageJson = readPackageJson(packageRoot);
|
|
738
|
-
const exported = packageExportTargetForConditions(packageJson.exports, subpath, conditions);
|
|
747
|
+
function resolvePackageAtRoot(packageRoot: string, subpath: string, conditions: readonly string[]) {
|
|
748
|
+
const packageJson = readPackageJson(packageRoot)
|
|
749
|
+
const exported = packageExportTargetForConditions(packageJson.exports, subpath, conditions)
|
|
739
750
|
if (exported) {
|
|
740
|
-
const resolved = probePackageTarget(path.resolve(packageRoot, exported), conditions)
|
|
741
|
-
if (resolved && isInside(packageRoot, resolved)) return resolved
|
|
751
|
+
const resolved = probePackageTarget(path.resolve(packageRoot, exported), conditions)
|
|
752
|
+
if (resolved && isInside(packageRoot, resolved)) return resolved
|
|
742
753
|
}
|
|
743
754
|
|
|
744
|
-
const onDisk = onDiskSubpath(packageRoot, subpath, conditions)
|
|
745
|
-
if (onDisk) return onDisk
|
|
755
|
+
const onDisk = onDiskSubpath(packageRoot, subpath, conditions)
|
|
756
|
+
if (onDisk) return onDisk
|
|
746
757
|
|
|
747
758
|
const edgeLight = conditions.includes('edge-light')
|
|
748
759
|
? [(packageJson as Record<string, unknown>)['edge-light']]
|
|
749
|
-
: []
|
|
750
|
-
const browser = conditions.includes('browser') ? [packageJson.browser] : []
|
|
760
|
+
: []
|
|
761
|
+
const browser = conditions.includes('browser') ? [packageJson.browser] : []
|
|
751
762
|
for (const entry of [...edgeLight, ...browser, packageJson.module, packageJson.main, './index']) {
|
|
752
|
-
if (typeof entry !== 'string') continue
|
|
753
|
-
const resolved = probePackageTarget(path.resolve(packageRoot, entry), conditions)
|
|
754
|
-
if (resolved) return resolved
|
|
763
|
+
if (typeof entry !== 'string') continue
|
|
764
|
+
const resolved = probePackageTarget(path.resolve(packageRoot, entry), conditions)
|
|
765
|
+
if (resolved) return resolved
|
|
755
766
|
}
|
|
756
767
|
|
|
757
|
-
return undefined
|
|
768
|
+
return undefined
|
|
758
769
|
}
|
|
759
770
|
|
|
760
771
|
function findNodePackageRoot(root: string, packageName: string) {
|
|
761
|
-
let dir = path.resolve(root)
|
|
772
|
+
let dir = path.resolve(root)
|
|
762
773
|
while (true) {
|
|
763
|
-
const candidate = path.join(dir, 'node_modules', packageName)
|
|
764
|
-
if (existsSync(path.join(candidate, 'package.json'))) return candidate
|
|
765
|
-
const parent = path.dirname(dir)
|
|
766
|
-
if (parent === dir) return undefined
|
|
767
|
-
dir = parent
|
|
774
|
+
const candidate = path.join(dir, 'node_modules', packageName)
|
|
775
|
+
if (existsSync(path.join(candidate, 'package.json'))) return candidate
|
|
776
|
+
const parent = path.dirname(dir)
|
|
777
|
+
if (parent === dir) return undefined
|
|
778
|
+
dir = parent
|
|
768
779
|
}
|
|
769
780
|
}
|
|
770
781
|
|
|
771
782
|
// One upward directory walk per (root, package) pair instead of one per import
|
|
772
783
|
// of it: the manifests it reads are already memoized (packageJsonCache), so the
|
|
773
784
|
// walk itself was the cost, repeated for every specifier a route's graph names.
|
|
774
|
-
const linkedPackageRootCache = new Map<string, string | undefined>()
|
|
785
|
+
const linkedPackageRootCache = new Map<string, string | undefined>()
|
|
775
786
|
// Bisect seam: `PNEXT_RESOLVE_LINK_MEMO=0` restores the walk-per-import path.
|
|
776
787
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
777
|
-
const memoLinkedRoots = process.env.PNEXT_RESOLVE_LINK_MEMO !== '0'
|
|
788
|
+
const memoLinkedRoots = process.env.PNEXT_RESOLVE_LINK_MEMO !== '0'
|
|
778
789
|
|
|
779
790
|
function findLinkedPackageRoot(root: string, packageName: string) {
|
|
780
|
-
if (!memoLinkedRoots) return walkForLinkedPackageRoot(root, packageName)
|
|
781
|
-
const key = `${path.resolve(root)}\0${packageName}
|
|
782
|
-
const cached = linkedPackageRootCache.get(key)
|
|
783
|
-
if (cached !== undefined || linkedPackageRootCache.has(key)) return cached
|
|
784
|
-
const found = walkForLinkedPackageRoot(root, packageName)
|
|
785
|
-
linkedPackageRootCache.set(key, found)
|
|
786
|
-
return found
|
|
791
|
+
if (!memoLinkedRoots) return walkForLinkedPackageRoot(root, packageName)
|
|
792
|
+
const key = `${path.resolve(root)}\0${packageName}`
|
|
793
|
+
const cached = linkedPackageRootCache.get(key)
|
|
794
|
+
if (cached !== undefined || linkedPackageRootCache.has(key)) return cached
|
|
795
|
+
const found = walkForLinkedPackageRoot(root, packageName)
|
|
796
|
+
linkedPackageRootCache.set(key, found)
|
|
797
|
+
return found
|
|
787
798
|
}
|
|
788
799
|
|
|
789
800
|
function walkForLinkedPackageRoot(root: string, packageName: string) {
|
|
790
|
-
let dir = path.resolve(root)
|
|
801
|
+
let dir = path.resolve(root)
|
|
791
802
|
while (true) {
|
|
792
|
-
const linked = linkedPackageRoot(dir, packageName)
|
|
793
|
-
if (linked) return linked
|
|
794
|
-
const parent = path.dirname(dir)
|
|
795
|
-
if (parent === dir) return undefined
|
|
796
|
-
dir = parent
|
|
803
|
+
const linked = linkedPackageRoot(dir, packageName)
|
|
804
|
+
if (linked) return linked
|
|
805
|
+
const parent = path.dirname(dir)
|
|
806
|
+
if (parent === dir) return undefined
|
|
807
|
+
dir = parent
|
|
797
808
|
}
|
|
798
809
|
}
|
|
799
810
|
|
|
800
811
|
function linkedPackageRoot(packageRoot: string, packageName: string) {
|
|
801
|
-
const packageJson = readPackageJson(packageRoot)
|
|
812
|
+
const packageJson = readPackageJson(packageRoot)
|
|
802
813
|
const specifier =
|
|
803
814
|
packageJson.dependencies?.[packageName] ??
|
|
804
815
|
packageJson.devDependencies?.[packageName] ??
|
|
805
816
|
packageJson.optionalDependencies?.[packageName] ??
|
|
806
|
-
packageJson.peerDependencies?.[packageName]
|
|
807
|
-
const relative = localDependencyPath(specifier)
|
|
808
|
-
if (!relative) return undefined
|
|
809
|
-
const candidate = path.resolve(packageRoot, relative)
|
|
810
|
-
const linkedPackageJson = readPackageJson(candidate)
|
|
811
|
-
return linkedPackageJson.name === packageName ? candidate : undefined
|
|
817
|
+
packageJson.peerDependencies?.[packageName]
|
|
818
|
+
const relative = localDependencyPath(specifier)
|
|
819
|
+
if (!relative) return undefined
|
|
820
|
+
const candidate = path.resolve(packageRoot, relative)
|
|
821
|
+
const linkedPackageJson = readPackageJson(candidate)
|
|
822
|
+
return linkedPackageJson.name === packageName ? candidate : undefined
|
|
812
823
|
}
|
|
813
824
|
|
|
814
825
|
function localDependencyPath(specifier: string | undefined) {
|
|
815
|
-
if (!specifier) return undefined
|
|
826
|
+
if (!specifier) return undefined
|
|
816
827
|
for (const prefix of ['link:', 'file:']) {
|
|
817
|
-
if (specifier.startsWith(prefix)) return specifier.slice(prefix.length)
|
|
828
|
+
if (specifier.startsWith(prefix)) return specifier.slice(prefix.length)
|
|
818
829
|
}
|
|
819
|
-
return specifier.startsWith('./') || specifier.startsWith('../') ? specifier : undefined
|
|
830
|
+
return specifier.startsWith('./') || specifier.startsWith('../') ? specifier : undefined
|
|
820
831
|
}
|
|
821
832
|
|
|
822
833
|
export function isEsmModuleFile(file: string) {
|
|
823
|
-
const ext = path.extname(file)
|
|
824
|
-
if (ext === '.mjs' || ext === '.mts') return true
|
|
825
|
-
if (ext === '.cjs' || ext === '.cts') return false
|
|
826
|
-
const packageRoot = nearestPackageRoot(path.dirname(file))
|
|
827
|
-
return Boolean(packageRoot && readPackageJson(packageRoot).type === 'module')
|
|
834
|
+
const ext = path.extname(file)
|
|
835
|
+
if (ext === '.mjs' || ext === '.mts') return true
|
|
836
|
+
if (ext === '.cjs' || ext === '.cts') return false
|
|
837
|
+
const packageRoot = nearestPackageRoot(path.dirname(file))
|
|
838
|
+
return Boolean(packageRoot && readPackageJson(packageRoot).type === 'module')
|
|
828
839
|
}
|
|
829
840
|
|
|
830
|
-
const esmEntryCache = new Map<string, boolean>()
|
|
841
|
+
const esmEntryCache = new Map<string, boolean>()
|
|
831
842
|
|
|
832
843
|
/**
|
|
833
844
|
* Whether a resolved package entry is really ESM. `isEsmModuleFile` reads only metadata (extension +
|
|
@@ -837,144 +848,144 @@ const esmEntryCache = new Map<string, boolean>();
|
|
|
837
848
|
* through to the content check.
|
|
838
849
|
*/
|
|
839
850
|
export function isEsmModuleEntry(file: string) {
|
|
840
|
-
if (isEsmModuleFile(file)) return true
|
|
841
|
-
if (path.extname(file) !== '.js') return false
|
|
842
|
-
const cached = esmEntryCache.get(file)
|
|
843
|
-
if (cached !== undefined) return cached
|
|
844
|
-
let esm = false
|
|
851
|
+
if (isEsmModuleFile(file)) return true
|
|
852
|
+
if (path.extname(file) !== '.js') return false
|
|
853
|
+
const cached = esmEntryCache.get(file)
|
|
854
|
+
if (cached !== undefined) return cached
|
|
855
|
+
let esm = false
|
|
845
856
|
try {
|
|
846
|
-
esm = !isCommonJsModuleSource(readFileSync(file, 'utf8'), file)
|
|
857
|
+
esm = !isCommonJsModuleSource(readFileSync(file, 'utf8'), file)
|
|
847
858
|
} catch {
|
|
848
859
|
// Unreadable entry: keep the conservative metadata answer.
|
|
849
860
|
}
|
|
850
|
-
esmEntryCache.set(file, esm)
|
|
851
|
-
return esm
|
|
861
|
+
esmEntryCache.set(file, esm)
|
|
862
|
+
return esm
|
|
852
863
|
}
|
|
853
864
|
|
|
854
865
|
export function isCommonJsModuleSource(source: string, file: string) {
|
|
855
|
-
const extension = path.extname(file)
|
|
856
|
-
if ((extension !== '.js' && extension !== '.cjs') || isEsmModuleFile(file)) return false
|
|
857
|
-
return !/^\s*(?:import(?:\s|[{'"*])|export(?:\s|[{*]))/m.test(source)
|
|
866
|
+
const extension = path.extname(file)
|
|
867
|
+
if ((extension !== '.js' && extension !== '.cjs') || isEsmModuleFile(file)) return false
|
|
868
|
+
return !/^\s*(?:import(?:\s|[{'"*])|export(?:\s|[{*]))/m.test(source)
|
|
858
869
|
}
|
|
859
870
|
|
|
860
871
|
export function commonJsModuleHasDefaultExport(source: string, file: string) {
|
|
861
872
|
return (
|
|
862
873
|
isCommonJsModuleSource(source, file) &&
|
|
863
874
|
(/\bexports\.default\s*=/.test(source) || /\bmodule\.exports\s*=/.test(source))
|
|
864
|
-
)
|
|
875
|
+
)
|
|
865
876
|
}
|
|
866
877
|
|
|
867
878
|
export function findWorkspaceRoot(root: string) {
|
|
868
|
-
const key = path.resolve(root)
|
|
869
|
-
if (workspaceRootCache.has(key)) return workspaceRootCache.get(key)
|
|
879
|
+
const key = path.resolve(root)
|
|
880
|
+
if (workspaceRootCache.has(key)) return workspaceRootCache.get(key)
|
|
870
881
|
|
|
871
|
-
let dir = key
|
|
882
|
+
let dir = key
|
|
872
883
|
while (true) {
|
|
873
884
|
if (readPackageJson(dir).workspaces || existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {
|
|
874
|
-
workspaceRootCache.set(key, dir)
|
|
875
|
-
return dir
|
|
885
|
+
workspaceRootCache.set(key, dir)
|
|
886
|
+
return dir
|
|
876
887
|
}
|
|
877
|
-
const parent = path.dirname(dir)
|
|
888
|
+
const parent = path.dirname(dir)
|
|
878
889
|
if (parent === dir) {
|
|
879
|
-
workspaceRootCache.set(key, undefined)
|
|
880
|
-
return undefined
|
|
890
|
+
workspaceRootCache.set(key, undefined)
|
|
891
|
+
return undefined
|
|
881
892
|
}
|
|
882
|
-
dir = parent
|
|
893
|
+
dir = parent
|
|
883
894
|
}
|
|
884
895
|
}
|
|
885
896
|
|
|
886
897
|
function isInside(root: string, file: string) {
|
|
887
|
-
const relative = path.relative(root, file)
|
|
888
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
898
|
+
const relative = path.relative(root, file)
|
|
899
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
889
900
|
}
|
|
890
901
|
|
|
891
902
|
function workspacePackageDirs(root: string) {
|
|
892
|
-
const workspaces = readPackageJson(root).workspaces
|
|
903
|
+
const workspaces = readPackageJson(root).workspaces
|
|
893
904
|
const patterns = [
|
|
894
905
|
...(Array.isArray(workspaces) ? workspaces : (workspaces?.packages ?? [])),
|
|
895
906
|
...readPnpmWorkspacePatterns(root),
|
|
896
|
-
]
|
|
897
|
-
const dirs = new Set<string>()
|
|
907
|
+
]
|
|
908
|
+
const dirs = new Set<string>()
|
|
898
909
|
|
|
899
910
|
for (const pattern of patterns) {
|
|
900
|
-
if (pattern.startsWith('!')) continue
|
|
901
|
-
const star = pattern.indexOf('*')
|
|
911
|
+
if (pattern.startsWith('!')) continue
|
|
912
|
+
const star = pattern.indexOf('*')
|
|
902
913
|
if (star === -1) {
|
|
903
|
-
dirs.add(path.resolve(root, pattern))
|
|
904
|
-
continue
|
|
914
|
+
dirs.add(path.resolve(root, pattern))
|
|
915
|
+
continue
|
|
905
916
|
}
|
|
906
917
|
|
|
907
|
-
const base = path.resolve(root, pattern.slice(0, star))
|
|
908
|
-
if (!existsSync(base)) continue
|
|
918
|
+
const base = path.resolve(root, pattern.slice(0, star))
|
|
919
|
+
if (!existsSync(base)) continue
|
|
909
920
|
for (const entry of readdirSync(base, { withFileTypes: true })) {
|
|
910
|
-
if (!entry.isDirectory()) continue
|
|
911
|
-
dirs.add(path.join(base, entry.name, pattern.slice(star + 1)))
|
|
921
|
+
if (!entry.isDirectory()) continue
|
|
922
|
+
dirs.add(path.join(base, entry.name, pattern.slice(star + 1)))
|
|
912
923
|
}
|
|
913
924
|
}
|
|
914
925
|
|
|
915
|
-
return [...dirs]
|
|
926
|
+
return [...dirs]
|
|
916
927
|
}
|
|
917
928
|
|
|
918
929
|
function readPnpmWorkspacePatterns(root: string) {
|
|
919
|
-
const file = path.join(root, 'pnpm-workspace.yaml')
|
|
920
|
-
if (!existsSync(file)) return []
|
|
930
|
+
const file = path.join(root, 'pnpm-workspace.yaml')
|
|
931
|
+
if (!existsSync(file)) return []
|
|
921
932
|
|
|
922
|
-
const patterns: string[] = []
|
|
923
|
-
let inPackages = false
|
|
933
|
+
const patterns: string[] = []
|
|
934
|
+
let inPackages = false
|
|
924
935
|
for (const line of readFileSync(file, 'utf8').split(/\r?\n/)) {
|
|
925
|
-
const trimmed = line.trim()
|
|
926
|
-
if (!trimmed || trimmed.startsWith('#')) continue
|
|
936
|
+
const trimmed = line.trim()
|
|
937
|
+
if (!trimmed || trimmed.startsWith('#')) continue
|
|
927
938
|
if (/^packages\s*:\s*$/.test(trimmed)) {
|
|
928
|
-
inPackages = true
|
|
929
|
-
continue
|
|
939
|
+
inPackages = true
|
|
940
|
+
continue
|
|
930
941
|
}
|
|
931
|
-
if (!inPackages) continue
|
|
932
|
-
const match = /^-\s*['"]?([^'"]+)['"]?\s*(?:#.*)?$/.exec(trimmed)
|
|
942
|
+
if (!inPackages) continue
|
|
943
|
+
const match = /^-\s*['"]?([^'"]+)['"]?\s*(?:#.*)?$/.exec(trimmed)
|
|
933
944
|
if (match?.[1]) {
|
|
934
|
-
patterns.push(match[1])
|
|
935
|
-
continue
|
|
945
|
+
patterns.push(match[1])
|
|
946
|
+
continue
|
|
936
947
|
}
|
|
937
|
-
if (/^\S/.test(line)) break
|
|
948
|
+
if (/^\S/.test(line)) break
|
|
938
949
|
}
|
|
939
|
-
return patterns
|
|
950
|
+
return patterns
|
|
940
951
|
}
|
|
941
952
|
|
|
942
|
-
const tsConfigCache = new Map<string, TsConfig>()
|
|
943
|
-
const packageJsonCache = new Map<string, PackageJson>()
|
|
944
|
-
const workspaceRootCache = new Map<string, string | undefined>()
|
|
945
|
-
const workspacePackageCache = new Map<string, Map<string, string>>()
|
|
953
|
+
const tsConfigCache = new Map<string, TsConfig>()
|
|
954
|
+
const packageJsonCache = new Map<string, PackageJson>()
|
|
955
|
+
const workspaceRootCache = new Map<string, string | undefined>()
|
|
956
|
+
const workspacePackageCache = new Map<string, Map<string, string>>()
|
|
946
957
|
|
|
947
958
|
function readTsConfig(root: string) {
|
|
948
|
-
const existing = tsConfigCache.get(root)
|
|
949
|
-
if (existing) return existing
|
|
950
|
-
const file = tsConfigFileFor(root)
|
|
951
|
-
const config = (file ? readJsonc<TsConfig>(file) : undefined) ?? {}
|
|
952
|
-
tsConfigCache.set(root, config)
|
|
953
|
-
return config
|
|
959
|
+
const existing = tsConfigCache.get(root)
|
|
960
|
+
if (existing) return existing
|
|
961
|
+
const file = tsConfigFileFor(root)
|
|
962
|
+
const config = (file ? readJsonc<TsConfig>(file) : undefined) ?? {}
|
|
963
|
+
tsConfigCache.set(root, config)
|
|
964
|
+
return config
|
|
954
965
|
}
|
|
955
966
|
|
|
956
967
|
function readPackageJson(root: string) {
|
|
957
|
-
const existing = packageJsonCache.get(root)
|
|
958
|
-
if (existing) return existing
|
|
959
|
-
const config = readJson<PackageJson>(path.join(root, 'package.json')) ?? {}
|
|
960
|
-
packageJsonCache.set(root, config)
|
|
961
|
-
return config
|
|
968
|
+
const existing = packageJsonCache.get(root)
|
|
969
|
+
if (existing) return existing
|
|
970
|
+
const config = readJson<PackageJson>(path.join(root, 'package.json')) ?? {}
|
|
971
|
+
packageJsonCache.set(root, config)
|
|
972
|
+
return config
|
|
962
973
|
}
|
|
963
974
|
|
|
964
975
|
function workspacePackages(root: string) {
|
|
965
|
-
const existing = workspacePackageCache.get(root)
|
|
966
|
-
if (existing) return existing
|
|
976
|
+
const existing = workspacePackageCache.get(root)
|
|
977
|
+
if (existing) return existing
|
|
967
978
|
|
|
968
|
-
const packages = new Map<string, string>()
|
|
979
|
+
const packages = new Map<string, string>()
|
|
969
980
|
for (const dir of workspacePackageDirs(root)) {
|
|
970
|
-
const packageJson = readPackageJson(dir)
|
|
971
|
-
if (packageJson.name) packages.set(packageJson.name, dir)
|
|
981
|
+
const packageJson = readPackageJson(dir)
|
|
982
|
+
if (packageJson.name) packages.set(packageJson.name, dir)
|
|
972
983
|
}
|
|
973
|
-
workspacePackageCache.set(root, packages)
|
|
974
|
-
return packages
|
|
984
|
+
workspacePackageCache.set(root, packages)
|
|
985
|
+
return packages
|
|
975
986
|
}
|
|
976
987
|
|
|
977
|
-
const workspaceMembershipCache = new Map<string, boolean>()
|
|
988
|
+
const workspaceMembershipCache = new Map<string, boolean>()
|
|
978
989
|
|
|
979
990
|
/**
|
|
980
991
|
* True when `name` is first-party workspace source. The workspace manifest (bun/npm `workspaces`,
|
|
@@ -983,122 +994,123 @@ const workspaceMembershipCache = new Map<string, boolean>();
|
|
|
983
994
|
* node_modules, so the package's own real dir is asked about its manifest too.
|
|
984
995
|
*/
|
|
985
996
|
export function isWorkspacePackage(root: string, name: string): boolean {
|
|
986
|
-
const key = `${path.resolve(root)}\0${name}
|
|
987
|
-
const cached = workspaceMembershipCache.get(key)
|
|
988
|
-
if (cached !== undefined) return cached
|
|
997
|
+
const key = `${path.resolve(root)}\0${name}`
|
|
998
|
+
const cached = workspaceMembershipCache.get(key)
|
|
999
|
+
if (cached !== undefined) return cached
|
|
989
1000
|
|
|
990
|
-
const workspaceRoot = findWorkspaceRoot(root)
|
|
991
|
-
let member = Boolean(workspaceRoot && workspacePackages(workspaceRoot).has(name))
|
|
1001
|
+
const workspaceRoot = findWorkspaceRoot(root)
|
|
1002
|
+
let member = Boolean(workspaceRoot && workspacePackages(workspaceRoot).has(name))
|
|
992
1003
|
if (!member) {
|
|
993
|
-
const packageRoot = findNodePackageRoot(path.resolve(root), name)
|
|
994
|
-
const real = packageRoot ? realImportPath(packageRoot) : undefined
|
|
995
|
-
const linkedRoot = real ? findWorkspaceRoot(real) : undefined
|
|
996
|
-
const declared = linkedRoot ? workspacePackages(linkedRoot).get(name) : undefined
|
|
997
|
-
member = Boolean(declared && realImportPath(declared) === real)
|
|
1004
|
+
const packageRoot = findNodePackageRoot(path.resolve(root), name)
|
|
1005
|
+
const real = packageRoot ? realImportPath(packageRoot) : undefined
|
|
1006
|
+
const linkedRoot = real ? findWorkspaceRoot(real) : undefined
|
|
1007
|
+
const declared = linkedRoot ? workspacePackages(linkedRoot).get(name) : undefined
|
|
1008
|
+
member = Boolean(declared && realImportPath(declared) === real)
|
|
998
1009
|
}
|
|
999
1010
|
|
|
1000
|
-
workspaceMembershipCache.set(key, member)
|
|
1001
|
-
return member
|
|
1011
|
+
workspaceMembershipCache.set(key, member)
|
|
1012
|
+
return member
|
|
1002
1013
|
}
|
|
1003
1014
|
|
|
1004
1015
|
export function workspacePackageRoots(root: string) {
|
|
1005
|
-
return [...workspacePackages(path.resolve(root)).values()].sort()
|
|
1016
|
+
return [...workspacePackages(path.resolve(root)).values()].sort()
|
|
1006
1017
|
}
|
|
1007
1018
|
|
|
1008
1019
|
function readJson<T>(file: string) {
|
|
1009
|
-
if (!existsSync(file)) return undefined
|
|
1010
|
-
return JSON.parse(readFileSync(file, 'utf8')) as T
|
|
1020
|
+
if (!existsSync(file)) return undefined
|
|
1021
|
+
return JSON.parse(readFileSync(file, 'utf8')) as T
|
|
1011
1022
|
}
|
|
1012
1023
|
|
|
1013
1024
|
function readJsonc<T>(file: string) {
|
|
1014
|
-
if (!existsSync(file)) return undefined
|
|
1015
|
-
return JSON.parse(stripTrailingCommas(stripJsonComments(readFileSync(file, 'utf8')))) as T
|
|
1025
|
+
if (!existsSync(file)) return undefined
|
|
1026
|
+
return JSON.parse(stripTrailingCommas(stripJsonComments(readFileSync(file, 'utf8')))) as T
|
|
1016
1027
|
}
|
|
1017
1028
|
|
|
1018
1029
|
function stripJsonComments(source: string) {
|
|
1019
|
-
let output = ''
|
|
1020
|
-
let inString = false
|
|
1021
|
-
let quote = ''
|
|
1022
|
-
let escaped = false
|
|
1030
|
+
let output = ''
|
|
1031
|
+
let inString = false
|
|
1032
|
+
let quote = ''
|
|
1033
|
+
let escaped = false
|
|
1023
1034
|
|
|
1024
1035
|
for (let index = 0; index < source.length; index += 1) {
|
|
1025
|
-
const char = source[index]
|
|
1026
|
-
const next = source[index + 1]
|
|
1036
|
+
const char = source[index]!
|
|
1037
|
+
const next = source[index + 1]
|
|
1027
1038
|
|
|
1028
1039
|
if (inString) {
|
|
1029
|
-
output += char
|
|
1040
|
+
output += char
|
|
1030
1041
|
if (escaped) {
|
|
1031
|
-
escaped = false
|
|
1042
|
+
escaped = false
|
|
1032
1043
|
} else if (char === '\\') {
|
|
1033
|
-
escaped = true
|
|
1044
|
+
escaped = true
|
|
1034
1045
|
} else if (char === quote) {
|
|
1035
|
-
inString = false
|
|
1046
|
+
inString = false
|
|
1036
1047
|
}
|
|
1037
|
-
continue
|
|
1048
|
+
continue
|
|
1038
1049
|
}
|
|
1039
1050
|
|
|
1040
1051
|
if (char === '"' || char === "'") {
|
|
1041
|
-
inString = true
|
|
1042
|
-
quote = char
|
|
1043
|
-
output += char
|
|
1044
|
-
continue
|
|
1052
|
+
inString = true
|
|
1053
|
+
quote = char
|
|
1054
|
+
output += char
|
|
1055
|
+
continue
|
|
1045
1056
|
}
|
|
1046
1057
|
|
|
1047
1058
|
if (char === '/' && next === '/') {
|
|
1048
|
-
while (index < source.length && source[index] !== '\n') index += 1
|
|
1049
|
-
output += '\n'
|
|
1050
|
-
continue
|
|
1059
|
+
while (index < source.length && source[index] !== '\n') index += 1
|
|
1060
|
+
output += '\n'
|
|
1061
|
+
continue
|
|
1051
1062
|
}
|
|
1052
1063
|
|
|
1053
1064
|
if (char === '/' && next === '*') {
|
|
1054
|
-
index += 2
|
|
1055
|
-
while (index < source.length && !(source[index] === '*' && source[index + 1] === '/'))
|
|
1056
|
-
|
|
1057
|
-
|
|
1065
|
+
index += 2
|
|
1066
|
+
while (index < source.length && !(source[index] === '*' && source[index + 1] === '/'))
|
|
1067
|
+
index += 1
|
|
1068
|
+
index += 1
|
|
1069
|
+
continue
|
|
1058
1070
|
}
|
|
1059
1071
|
|
|
1060
|
-
output += char
|
|
1072
|
+
output += char
|
|
1061
1073
|
}
|
|
1062
1074
|
|
|
1063
|
-
return output
|
|
1075
|
+
return output
|
|
1064
1076
|
}
|
|
1065
1077
|
|
|
1066
1078
|
function stripTrailingCommas(source: string) {
|
|
1067
|
-
let output = ''
|
|
1068
|
-
let inString = false
|
|
1069
|
-
let quote = ''
|
|
1070
|
-
let escaped = false
|
|
1079
|
+
let output = ''
|
|
1080
|
+
let inString = false
|
|
1081
|
+
let quote = ''
|
|
1082
|
+
let escaped = false
|
|
1071
1083
|
|
|
1072
1084
|
for (let index = 0; index < source.length; index += 1) {
|
|
1073
|
-
const char = source[index]
|
|
1085
|
+
const char = source[index]!
|
|
1074
1086
|
|
|
1075
1087
|
if (inString) {
|
|
1076
|
-
output += char
|
|
1088
|
+
output += char
|
|
1077
1089
|
if (escaped) {
|
|
1078
|
-
escaped = false
|
|
1090
|
+
escaped = false
|
|
1079
1091
|
} else if (char === '\\') {
|
|
1080
|
-
escaped = true
|
|
1092
|
+
escaped = true
|
|
1081
1093
|
} else if (char === quote) {
|
|
1082
|
-
inString = false
|
|
1094
|
+
inString = false
|
|
1083
1095
|
}
|
|
1084
|
-
continue
|
|
1096
|
+
continue
|
|
1085
1097
|
}
|
|
1086
1098
|
|
|
1087
1099
|
if (char === '"' || char === "'") {
|
|
1088
|
-
inString = true
|
|
1089
|
-
quote = char
|
|
1090
|
-
output += char
|
|
1091
|
-
continue
|
|
1100
|
+
inString = true
|
|
1101
|
+
quote = char
|
|
1102
|
+
output += char
|
|
1103
|
+
continue
|
|
1092
1104
|
}
|
|
1093
1105
|
|
|
1094
1106
|
if (char === ',') {
|
|
1095
|
-
let nextIndex = index + 1
|
|
1096
|
-
while (/\s/.test(source[nextIndex] ?? '')) nextIndex += 1
|
|
1097
|
-
if (source[nextIndex] === '}' || source[nextIndex] === ']') continue
|
|
1107
|
+
let nextIndex = index + 1
|
|
1108
|
+
while (/\s/.test(source[nextIndex] ?? '')) nextIndex += 1
|
|
1109
|
+
if (source[nextIndex] === '}' || source[nextIndex] === ']') continue
|
|
1098
1110
|
}
|
|
1099
1111
|
|
|
1100
|
-
output += char
|
|
1112
|
+
output += char
|
|
1101
1113
|
}
|
|
1102
1114
|
|
|
1103
|
-
return output
|
|
1115
|
+
return output
|
|
1104
1116
|
}
|