Skip to content

Auto-detect dependency export subpaths from package.json - #75

Merged
titouanmathis merged 3 commits into
mainfrom
feat/auto-detect-subpaths
Aug 6, 2026
Merged

Auto-detect dependency export subpaths from package.json#75
titouanmathis merged 3 commits into
mainfrom
feat/auto-detect-subpaths

Conversation

@titouanmathis

Copy link
Copy Markdown
Contributor

Problem

Registering a package that exposes many export subpaths means declaring each one by hand. For esm.sh deps you have to list both @studiometa/js-toolkit and @studiometa/js-toolkit/utils; for self-hosted deps you have to spell out every entry in the entries map (added in #74). This does not scale for a package like @studiometa/ui with ~190 subpaths.

Fix

Add a subpaths option to DependencyConfig that auto-detects a package's export subpaths from its package.json exports field:

subpaths?: boolean | string[];   // true = all exports, [...] = an explicit subset

esm.sh dependencies (no source)

{ specifier: '@studiometa/js-toolkit', esmSh: { bundle: false }, subpaths: true }

subpaths: true reads the package's exportsfrom disk (node_modules) first, falling back to the npm registry when the package is not installed locally — and adds each subpath to the import map as its own esm.sh URL. So @studiometa/js-toolkit/utils appears automatically. subpaths: ['./utils'] uses an explicit list and reads nothing.

Local self-hosted dependencies (local source)

{ specifier: 'demo-lib', source: './lib/**/*.ts', subpaths: true }

subpaths: true reads the package root's package.json exports (root derived by stripping the glob from source) and derives the multi-entry code-split entries — each subpath mapped to its .ts target. Subpaths that resolve to the same file (e.g. ./Foo and ./Foo.js) are grouped: the non-.js key becomes the built entry, the .js key becomes an import-map alias to the same emitted file (avoids a Foo.js.js filename). Explicit entries still take precedence.

resolveDependencies is now async to allow the registry fallback.

End-to-end proof (demo)

The demo switches both dependency kinds to subpaths: true:

dependencies: [
  { specifier: '@studiometa/js-toolkit', esmSh: { bundle: false }, subpaths: true },
  { specifier: 'demo-lib', source: './lib/**/*.ts', subpaths: true },
]

A new packages/demo/lib/package.json declares the local exports map. npm run demo:build emits static/deps/demo-lib/{index,manifest}.js (+ the shared greeter chunk) and an import map containing @studiometa/js-toolkit, @studiometa/js-toolkit/utils, demo-lib, and demo-lib/manifest.

Backward compatibility

Purely additive. String deps, { specifier }, { source }, { entry }, and explicit { entries } forms are unchanged. Existing tests remain green.

Tests

  • esm.sh: array subset, true (disk read via the real @studiometa/js-toolkit), and registry fallback (stubbed fetch).
  • Local derivation: exports → entries, .js-alias dedup (one entry, alias import-map key), explicit-entries-wins.
  • extractSubpathKeys / resolveExportTarget units (skip ./package.json + wildcards, resolve conditions objects).
  • Plugin: alias specifiers get the publicPath prefix alongside entry specifiers.

152 tests pass (+17); lint, type-check, and npm run build clean.

Release

Additive, backward-compatible — would ship as 0.3.12. Not published here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Botz34NmFLdgRgm2QJpKkZ

titouanmathis and others added 3 commits August 6, 2026 09:29
Introduce a `subpaths` option on `DependencyConfig` that expands a package's
export subpaths automatically instead of declaring each one by hand.

- esm.sh dependencies: `subpaths: true` reads the package's `exports` (disk
  node_modules first, npm registry fallback) and adds each subpath to the
  import map as its own esm.sh URL; the array form takes an explicit subset.
- Local self-hosted dependencies: `subpaths: true` derives the multi-entry
  code-split `entries` from `exports`, collapsing `.js` export aliases onto
  the canonical entry to avoid duplicate chunks. Explicit `entries` still win.

resolveDependencies is now async to allow the registry fallback. The demo uses
`subpaths: true` for both @studiometa/js-toolkit (esm.sh) and demo-lib (local)
as an end-to-end proof.

Co-authored-by: Claude <claude@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Botz34NmFLdgRgm2QJpKkZ
Co-authored-by: Claude <claude@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Botz34NmFLdgRgm2QJpKkZ
Co-authored-by: Claude <claude@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Botz34NmFLdgRgm2QJpKkZ
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 6, 2026

Copy link
Copy Markdown

Deploying studiometa-playground with  Cloudflare Pages  Cloudflare Pages

Latest commit: 85520b4
Status: ✅  Deploy successful!
Preview URL: https://c626e7d9.studiometa-playground.pages.dev
Branch Preview URL: https://feat-auto-detect-subpaths.studiometa-playground.pages.dev

View logs

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

Size Change: +1.46 kB (+2.8%)

Total Size: 53.5 kB

📦 View Changed
Filename Size Change
packages/playground/dist/lib/plugins/PlaygroundDependenciesPlugin.js 3.81 kB +13 B (+0.34%)
packages/playground/dist/lib/presets/playground.js 1.07 kB +2 B (+0.19%)
packages/playground/dist/lib/utils/resolve-dependencies.js 3.04 kB +1.44 kB (+90.59%) 🆘
ℹ️ View Unchanged
Filename Size
packages/playground-preview/dist/element.js 10 kB
packages/playground-preview/dist/index.js 10 kB
packages/playground/dist/front/css/app.css 4.26 kB
packages/playground/dist/front/js/app.js 139 B
packages/playground/dist/front/js/components/Editor.js 929 B
packages/playground/dist/front/js/components/Editors.js 265 B
packages/playground/dist/front/js/components/EditorVisibility.js 343 B
packages/playground/dist/front/js/components/HeaderSwitcher.js 436 B
packages/playground/dist/front/js/components/HtmlEditor.js 748 B
packages/playground/dist/front/js/components/Iframe.js 1.74 kB
packages/playground/dist/front/js/components/IframeReloader.js 182 B
packages/playground/dist/front/js/components/LayoutReactive.js 616 B
packages/playground/dist/front/js/components/LayoutSwitcher.js 341 B
packages/playground/dist/front/js/components/Playground.js 1.14 kB
packages/playground/dist/front/js/components/Resizable.js 992 B
packages/playground/dist/front/js/components/ResizableCursor.js 298 B
packages/playground/dist/front/js/components/ResizableSync.js 512 B
packages/playground/dist/front/js/components/ScriptEditor.js 520 B
packages/playground/dist/front/js/components/StyleEditor.js 247 B
packages/playground/dist/front/js/components/Switcher.js 334 B
packages/playground/dist/front/js/components/ThemeSwitcher.js 456 B
packages/playground/dist/front/js/create-playground.js 196 B
packages/playground/dist/front/js/loaders/html.js 124 B
packages/playground/dist/front/js/loaders/script.js 124 B
packages/playground/dist/front/js/loaders/style.js 124 B
packages/playground/dist/front/js/store/config.js 468 B
packages/playground/dist/front/js/store/content.js 400 B
packages/playground/dist/front/js/store/header.js 573 B
packages/playground/dist/front/js/store/index.js 109 B
packages/playground/dist/front/js/store/layout.js 606 B
packages/playground/dist/front/js/store/theme.js 516 B
packages/playground/dist/front/js/utils/js/index.js 436 B
packages/playground/dist/front/js/utils/monaco.js 844 B
packages/playground/dist/front/js/utils/patch-iframe-url.js 362 B
packages/playground/dist/front/js/utils/resolve-import-map-urls.js 246 B
packages/playground/dist/front/js/utils/storage/AbstractStorageProvider.js 138 B
packages/playground/dist/front/js/utils/storage/FallbackStorageProvider.js 266 B
packages/playground/dist/front/js/utils/storage/index.js 479 B
packages/playground/dist/front/js/utils/storage/LocalStorageProvider.js 254 B
packages/playground/dist/front/js/utils/storage/MemoryStorageProvider.js 206 B
packages/playground/dist/front/js/utils/storage/MultiStorageProvider.js 307 B
packages/playground/dist/front/js/utils/storage/StorageProviderInterface.js 73 B
packages/playground/dist/front/js/utils/storage/SyncedStorageProvider.js 292 B
packages/playground/dist/front/js/utils/storage/URLStorageProvider.js 365 B
packages/playground/dist/front/js/utils/storage/WatchableStore.js 307 B
packages/playground/dist/front/js/utils/storage/ZipStorageProvider.js 271 B
packages/playground/dist/front/js/utils/twig/index.js 435 B
packages/playground/dist/index.js 154 B
packages/playground/dist/lib/plugins/PlaygroundLoadersPlugin.js 424 B
packages/playground/dist/lib/presets/html-webpack-script-type-module.js 288 B
packages/playground/dist/lib/presets/production-build.js 261 B
packages/playground/dist/lib/tailwind-config.js 509 B
packages/playground/dist/lib/utils/resolve-public-path.js 283 B
packages/playground/dist/lib/utils/zip.js 310 B
packages/playground/dist/preset.js 190 B
packages/playground/dist/tailwind.js 113 B

compressed-size-action

@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.95%. Comparing base (7b5c815) to head (85520b4).

Files with missing lines Patch % Lines
...s/playground/src/lib/utils/resolve-dependencies.ts 80.64% 8 Missing and 10 partials ⚠️
packages/playground/src/lib/presets/playground.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #75      +/-   ##
==========================================
+ Coverage   29.96%   33.95%   +3.99%     
==========================================
  Files          55       55              
  Lines        1038     1128      +90     
  Branches      203      230      +27     
==========================================
+ Hits          311      383      +72     
- Misses        709      717       +8     
- Partials       18       28      +10     
Flag Coverage Δ
playground 33.95% <80.00%> (+3.99%) ⬆️
playground-preview 33.95% <80.00%> (+3.99%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@titouanmathis
titouanmathis merged commit 3267daf into main Aug 6, 2026
8 checks passed
@titouanmathis
titouanmathis deleted the feat/auto-detect-subpaths branch August 6, 2026 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant