Skip to content

Commit 9aa90c4

Browse files
authored
feat: support pkg.imports in playground (#1311)
* feat: support pkg.imports in playground * tidy up
1 parent 94dc0fa commit 9aa90c4

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

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

Lines changed: 21 additions & 10 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,22 @@ 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);
211+
if (current) {
212+
const { name, version } = current.meta;
206213
const path = new URL(importee, importer).href.replace(`${NPM}/${name}@${version}/`, '');
207214

208-
return normalize_path(pkg, path);
215+
return normalize_path(current, path);
209216
}
210217

211218
return new URL(importee, importer).href;
212219
}
213220

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

224237
let default_version = 'latest';
225238

226-
if (importer.startsWith(NPM)) {
239+
if (current) {
227240
// 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);
241+
const { meta } = current;
231242

232243
if (meta.name === pkg_name) {
233244
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)