Skip to content

Commit 9062ef1

Browse files
committed
feat: support pkg.imports in playground
1 parent 94dc0fa commit 9062ef1

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

packages/repl/src/lib/workers/bundler/index.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import {
2727
parse_npm_url,
2828
resolve_local,
2929
resolve_subpath,
30-
resolve_version
30+
resolve_version,
31+
type Package
3132
} from '../npm';
3233
import type { BundleResult } from '$lib/public';
3334

@@ -180,6 +181,14 @@ async function get_bundle(
180181
// importing from a URL
181182
if (/^[a-z]+:/.test(importee)) return importee;
182183

184+
/** The npm package we're importing from, if any */
185+
let current: null | Package;
186+
187+
if (importer.startsWith(NPM)) {
188+
const { name, version } = parse_npm_url(importer);
189+
current = await fetch_package(name, name === 'svelte' ? svelte_version : version);
190+
}
191+
183192
// importing a relative file
184193
if (importee[0] === '.') {
185194
if (importer.startsWith(VIRTUAL)) {
@@ -199,18 +208,24 @@ async function get_bundle(
199208
);
200209
}
201210

202-
if (importer.startsWith(NPM)) {
203-
const { name, version } = parse_npm_url(importer);
204-
205-
const pkg = await fetch_package(name, name === 'svelte' ? svelte_version : version);
206-
const path = new URL(importee, importer).href.replace(`${NPM}/${name}@${version}/`, '');
211+
if (current) {
212+
const path = new URL(importee, importer).href.replace(
213+
`${NPM}/${current.meta.name}@${current.meta.version}/`,
214+
''
215+
);
207216

208-
return normalize_path(pkg, path);
217+
return normalize_path(current, path);
209218
}
210219

211220
return new URL(importee, importer).href;
212221
}
213222

223+
// importing a file from the same package via pkg.imports
224+
if (importee[0] === '#' && current) {
225+
const subpath = resolve_subpath(current, importee);
226+
return normalize_path(current, subpath.slice(2));
227+
}
228+
214229
// importing an external package -> `npm://$/<name>@<version>/<path>`
215230
const match = /^((?:@[^/]+\/)?[^/@]+)(?:@([^/]+))?(\/.+)?$/.exec(importee);
216231
if (!match) throw new Error(`Invalid import "${importee}"`);
@@ -223,11 +238,9 @@ async function get_bundle(
223238

224239
let default_version = 'latest';
225240

226-
if (importer.startsWith(NPM)) {
241+
if (current) {
227242
// use the version specified in importer's package.json, not `latest`
228-
const { name, version } = parse_npm_url(importer);
229-
230-
const { meta } = await fetch_package(name, name === 'svelte' ? svelte_version : version);
243+
const { meta } = current;
231244

232245
if (meta.name === pkg_name) {
233246
default_version = meta.version;

packages/repl/src/lib/workers/npm.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as resolve from 'resolve.exports';
22
import { parseTar, type FileDescription } from 'tarparser';
33
import { NPM } from './constants';
44

5-
interface Package {
5+
export interface Package {
66
meta: any; // package.json contents
77
contents: Record<string, FileDescription>;
88
}
@@ -126,6 +126,21 @@ export function resolve_subpath(pkg: Package, subpath: string): string {
126126
return `./${pkg.meta.svelte.replace('./', '')}`;
127127
}
128128

129+
if (subpath[0] === '#') {
130+
try {
131+
const resolved = resolve.imports(pkg.meta, subpath, {
132+
browser: true,
133+
conditions: ['svelte', 'module', 'browser', 'development']
134+
});
135+
136+
return resolved?.[0] as string;
137+
} catch {
138+
throw new Error(
139+
`No matched import path was found for "${subpath}" in "${pkg.meta.name}/package.json"`
140+
);
141+
}
142+
}
143+
129144
// modern
130145
if (pkg.meta.exports) {
131146
try {

0 commit comments

Comments
 (0)