diff --git a/.changeset/rich-seahorses-walk.md b/.changeset/rich-seahorses-walk.md
new file mode 100644
index 000000000000..ccb9a5405561
--- /dev/null
+++ b/.changeset/rich-seahorses-walk.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Resolve \$lib alias when packaging
diff --git a/packages/kit/src/packaging/index.js b/packages/kit/src/packaging/index.js
index 7a82a6cef0a2..d72b677342c9 100644
--- a/packages/kit/src/packaging/index.js
+++ b/packages/kit/src/packaging/index.js
@@ -14,11 +14,19 @@ const essential_files = ['README', 'LICENSE', 'CHANGELOG', '.gitignore', '.npmig
* @param {string} cwd
*/
export async function make_package(config, cwd = process.cwd()) {
- rimraf(path.join(cwd, config.kit.package.dir));
+ const abs_package_dir = path.join(cwd, config.kit.package.dir);
+ rimraf(abs_package_dir);
if (config.kit.package.emitTypes) {
// Generate type definitions first so hand-written types can overwrite generated ones
await emit_dts(config);
+ // Resolve aliases, TS leaves them as-is
+ const files = walk(abs_package_dir);
+ for (const file of files) {
+ const filename = path.join(abs_package_dir, file);
+ const source = fs.readFileSync(filename, 'utf8');
+ fs.writeFileSync(filename, resolve_$lib_alias(file, source, config));
+ }
}
const files_filter = create_filter(config.kit.package.files);
@@ -47,7 +55,7 @@ export async function make_package(config, cwd = process.cwd()) {
if (!files_filter(file.replace(/\\/g, '/'))) {
const dts_file = (svelte_ext ? file : file.slice(0, -ext.length)) + '.d.ts';
- const dts_path = path.join(cwd, config.kit.package.dir, dts_file);
+ const dts_path = path.join(abs_package_dir, dts_file);
if (fs.existsSync(dts_path)) fs.unlinkSync(dts_path);
continue;
}
@@ -72,7 +80,7 @@ export async function make_package(config, cwd = process.cwd()) {
// TypeScript's declaration emit won't copy over the d.ts files, so we do it here
out_file = file;
out_contents = source;
- if (fs.existsSync(path.join(cwd, config.kit.package.dir, out_file))) {
+ if (fs.existsSync(path.join(abs_package_dir, out_file))) {
console.warn(
'Found already existing file from d.ts generation for ' +
out_file +
@@ -86,8 +94,9 @@ export async function make_package(config, cwd = process.cwd()) {
out_file = file;
out_contents = source;
}
+ out_contents = resolve_$lib_alias(out_file, out_contents, config);
- write(path.join(cwd, config.kit.package.dir, out_file), out_contents);
+ write(path.join(abs_package_dir, out_file), out_contents);
if (exports_filter(file)) {
const original = `$lib/${file.replace(/\\/g, '/')}`;
@@ -134,7 +143,7 @@ export async function make_package(config, cwd = process.cwd()) {
}
}
- write(path.join(cwd, config.kit.package.dir, 'package.json'), JSON.stringify(pkg, null, ' '));
+ write(path.join(abs_package_dir, 'package.json'), JSON.stringify(pkg, null, ' '));
const whitelist = fs.readdirSync(cwd).filter((file) => {
const lowercased = file.toLowerCase();
@@ -144,11 +153,46 @@ export async function make_package(config, cwd = process.cwd()) {
const full_path = path.join(cwd, pathname);
if (fs.lstatSync(full_path).isDirectory()) continue; // just to be sure
- const package_path = path.join(cwd, config.kit.package.dir, pathname);
+ const package_path = path.join(abs_package_dir, pathname);
if (!fs.existsSync(package_path)) fs.copyFileSync(full_path, package_path);
}
}
+/**
+ * Resolves the `$lib` alias.
+ *
+ * TODO: make this more generic to also handle other aliases the user could have defined
+ * via `kit.vite.resolve.alias`. Also investage how to do this in a more robust way
+ * (right now regex string replacement is used).
+ * For more discussion see https://github.com/sveltejs/kit/pull/2453
+ *
+ * @param {string} file Relative to the lib root
+ * @param {string} content
+ * @param {import('types/config').ValidatedConfig} config
+ * @returns {string}
+ */
+function resolve_$lib_alias(file, content, config) {
+ /**
+ * @param {string} match
+ * @param {string} _
+ * @param {string} import_path
+ */
+ const replace_import_path = (match, _, import_path) => {
+ if (!import_path.startsWith('$lib/')) {
+ return match;
+ }
+
+ const full_path = path.join(config.kit.files.lib, file);
+ const full_import_path = path.join(config.kit.files.lib, import_path.slice('$lib/'.length));
+ let resolved = path.relative(path.dirname(full_path), full_import_path).replace(/\\/g, '/');
+ resolved = resolved.startsWith('.') ? resolved : './' + resolved;
+ return match.replace(import_path, resolved);
+ };
+ content = content.replace(/from\s+('|")([^"';,]+?)\1/g, replace_import_path);
+ content = content.replace(/import\s*\(\s*('|")([^"';,]+?)\1\s*\)/g, replace_import_path);
+ return content;
+}
+
/**
* @param {string} filename
* @param {string} source
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte
new file mode 100644
index 000000000000..1463588b2228
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte
@@ -0,0 +1,4 @@
+
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte.d.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte.d.ts
new file mode 100644
index 000000000000..613984c1649b
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/Test.svelte.d.ts
@@ -0,0 +1,15 @@
+import { SvelteComponentTyped } from 'svelte';
+declare const __propDef: {
+ props: {
+ bar?: import('./sub/foo').Foo;
+ };
+ events: {
+ [evt: string]: CustomEvent;
+ };
+ slots: {};
+};
+export declare type TestProps = typeof __propDef.props;
+export declare type TestEvents = typeof __propDef.events;
+export declare type TestSlots = typeof __propDef.slots;
+export default class Test extends SvelteComponentTyped {}
+export {};
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.d.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.d.ts
new file mode 100644
index 000000000000..85f482c14ba7
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.d.ts
@@ -0,0 +1,4 @@
+export interface Baz {
+ baz: string;
+}
+export declare const baz: Baz;
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.js b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.js
new file mode 100644
index 000000000000..844535e7bc66
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/baz.js
@@ -0,0 +1 @@
+export const baz = { baz: 'baz' };
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.d.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.d.ts
new file mode 100644
index 000000000000..4c44188c3648
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.d.ts
@@ -0,0 +1 @@
+export { default as Test } from './Test.svelte';
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.js b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.js
new file mode 100644
index 000000000000..4c44188c3648
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/index.js
@@ -0,0 +1 @@
+export { default as Test } from './Test.svelte';
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/package.json b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/package.json
new file mode 100644
index 000000000000..78ebd4d10fb4
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "resolve-alias",
+ "version": "1.0.0",
+ "description": "package using $lib alias",
+ "type": "module",
+ "exports": {
+ "./package.json": "./package.json",
+ "./Test.svelte": "./Test.svelte",
+ ".": "./index.js",
+ "./baz": "./baz.js",
+ "./sub/bar": "./sub/bar.js",
+ "./sub/foo": "./sub/foo.js"
+ },
+ "svelte": "./index.js"
+}
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.d.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.d.ts
new file mode 100644
index 000000000000..9f1a49e9dfd6
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.d.ts
@@ -0,0 +1,2 @@
+export declare const bar1: import('./foo').Foo;
+export declare const bar2: import('../baz').Baz;
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.js b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.js
new file mode 100644
index 000000000000..17941b746387
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/bar.js
@@ -0,0 +1,4 @@
+import { baz } from '../baz';
+import { foo } from './foo';
+export const bar1 = foo;
+export const bar2 = baz;
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.d.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.d.ts
new file mode 100644
index 000000000000..b5b3928ab61d
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.d.ts
@@ -0,0 +1,4 @@
+export interface Foo {
+ foo: string;
+}
+export declare const foo: Foo;
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.js b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.js
new file mode 100644
index 000000000000..aaae90ec5bfc
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/expected/sub/foo.js
@@ -0,0 +1 @@
+export const foo = { foo: 'foo' };
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json b/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json
new file mode 100644
index 000000000000..65358d9a9a8a
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "resolve-alias",
+ "version": "1.0.0",
+ "description": "package using $lib alias"
+}
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/app.html b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/app.html
new file mode 100644
index 000000000000..245305c4ef5b
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %svelte.head%
+
+
+ %svelte.body%
+
+
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/Test.svelte b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/Test.svelte
new file mode 100644
index 000000000000..6ba757b638c1
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/Test.svelte
@@ -0,0 +1,5 @@
+
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/baz.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/baz.ts
new file mode 100644
index 000000000000..7fe0964e7187
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/baz.ts
@@ -0,0 +1,5 @@
+export interface Baz {
+ baz: string;
+}
+
+export const baz: Baz = { baz: 'baz' };
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/index.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/index.ts
new file mode 100644
index 000000000000..abb9e1104b39
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/index.ts
@@ -0,0 +1 @@
+export { default as Test } from '$lib/Test.svelte';
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/bar.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/bar.ts
new file mode 100644
index 000000000000..335e08c551d3
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/bar.ts
@@ -0,0 +1,5 @@
+import { baz } from '$lib/baz';
+import { foo } from '$lib/sub/foo';
+
+export const bar1 = foo;
+export const bar2 = baz;
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/foo.ts b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/foo.ts
new file mode 100644
index 000000000000..f1cea24ce4ef
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/src/lib/sub/foo.ts
@@ -0,0 +1,5 @@
+export interface Foo {
+ foo: string;
+}
+
+export const foo: Foo = { foo: 'foo' };
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs b/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs
new file mode 100644
index 000000000000..d0526bbb674d
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs
@@ -0,0 +1,5 @@
+const preprocess = require('svelte-preprocess');
+
+module.exports = {
+ preprocess: preprocess()
+};
diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/tsconfig.json b/packages/kit/src/packaging/test/fixtures/resolve-alias/tsconfig.json
new file mode 100644
index 000000000000..0f54c3906f8b
--- /dev/null
+++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "moduleResolution": "node",
+ "module": "es2020",
+ "lib": ["es2020", "DOM"],
+ "target": "es2019",
+ /**
+ svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
+ to enforce using \`import type\` instead of \`import\` for Types.
+ */
+ "importsNotUsedAsValues": "error",
+ "isolatedModules": true,
+ "resolveJsonModule": true,
+ /**
+ To have warnings/errors of the Svelte compiler at the correct position,
+ enable source maps by default.
+ */
+ "sourceMap": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": ".",
+ "allowJs": true,
+ "checkJs": true,
+ "paths": {
+ "$lib/*": ["src/lib/*"]
+ }
+ },
+ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
+}
diff --git a/packages/kit/src/packaging/test/index.js b/packages/kit/src/packaging/test/index.js
index df0f01eef027..c7e01dbb8c31 100644
--- a/packages/kit/src/packaging/test/index.js
+++ b/packages/kit/src/packaging/test/index.js
@@ -113,4 +113,8 @@ test('create package with files.exclude settings', async () => {
await test_make_package('files-exclude');
});
+test('create package and resolves $lib alias', async () => {
+ await test_make_package('resolve-alias');
+});
+
test.run();
diff --git a/packages/kit/tsconfig.json b/packages/kit/tsconfig.json
index b288e319af6f..e407884ba5f3 100644
--- a/packages/kit/tsconfig.json
+++ b/packages/kit/tsconfig.json
@@ -16,5 +16,6 @@
"types/*": ["./types/*"]
}
},
- "include": ["src/**/*", "test/**/*", "types/**/*"]
+ "include": ["src/**/*", "test/**/*", "types/**/*"],
+ "exclude": ["src/packaging/test/fixtures/**/*"]
}