Repository: sveltejs/kit (js)

Issue:
npm run check make app reload and CSP blocks the navigation
### Describe the bug

I start development. The app starts in the browser. Everything works.

I launch in another shell's console "`npm run check`" and then the browser reloads the page and I cannot use more the app because of the below errors (I'm using CSP):

```shell
Refused to connect to 'ws://localhost:4000/' because it violates the following Content Security Policy directive: "default-src https://*.project.com". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
```

In my `svelte.config.js` I have this:

```js
import adapter from "@sveltejs/adapter-static";
import { vitePreprocess } from "@sveltejs/kit/vite";
import "dotenv/config";

const dev = process.env.NODE_ENV === "development";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: vitePreprocess(),

  kit: {
    adapter: adapter({
      fallback: "index.html",
    }),

    serviceWorker: {
      register: !dev,
    },

    csp: dev
      ? undefined
      : {
          directives: {
            "default-src": [`https://*.${process.env.PUBLIC_PROJECT_URL}`],
            "style-src": [
              `https://*.${process.env.PUBLIC_PROJECT_URL}`,
              "unsafe-inline",
            ],
            "img-src": ["*", "data:"],
          },
        },
  },
};

export default config;
```

I think `npm run check` is restarting the app without `process.env.NODE_ENV === 'development'`.

My `npm run check` is: `"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"`.

**Is there a way to disable CSP during development?**

### System Info

```Shell
System:
    OS: Windows 10 10.0.19045
  Binaries:
    Node: 18.13.0
    npm: 8.19.3
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (107.0.1418.62)
  npmPackages:
    @sveltejs/adapter-static: 1.0.2 => 1.0.2
    @sveltejs/kit: 1.1.0 => 1.1.0
    svelte: 3.55.1 => 3.55.1
    vite: 4.0.4 => 4.0.4
```

### Severity

blocking an upgrade

### Additional Information

This didn't happen with `@sveltejs/kit@1.0.2`.


Pull request:
fix: only generate typing files with sync command
fixes #8525

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.


Patch:
diff --git a/.changeset/clean-onions-doubt.md b/.changeset/clean-onions-doubt.md
new file mode 100644
index 000000000..305fd6296
--- /dev/null
+++ b/.changeset/clean-onions-doubt.md
@@ -0,0 +1,5 @@
+---
+"@sveltejs/kit": patch
+---
+
+fix: correct link in types documentation
diff --git a/.changeset/neat-geckos-end.md b/.changeset/neat-geckos-end.md
new file mode 100644
index 000000000..dcfc1d4b3
--- /dev/null
+++ b/.changeset/neat-geckos-end.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: only generate type definitions with `sync` command
diff --git a/.changeset/thick-hats-poke.md b/.changeset/thick-hats-poke.md
new file mode 100644
index 000000000..33d5eca92
--- /dev/null
+++ b/.changeset/thick-hats-poke.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: remove baseUrl to prevent wrong TypeScript auto imports if possible
diff --git a/documentation/docs/20-core-concepts/20-load.md b/documentation/docs/20-core-concepts/20-load.md
index 834f4101c..ebea67a84 100644
--- a/documentation/docs/20-core-concepts/20-load.md
+++ b/documentation/docs/20-core-concepts/20-load.md
@@ -164,7 +164,7 @@ Conceptually, they're the same thing, but there are some important differences t
 
 ### Input
 
-Both universal and server `load` functions have access to properties describing the request (`params`, `route` and `url`) and various functions (`depends`, `fetch` and `parent`). These are described in the following sections.
+Both universal and server `load` functions have access to properties describing the request (`params`, `route` and `url`) and various functions (`fetch`, `setHeaders`, `parent` and `depends`). These are described in the following sections.
 
 Server `load` functions are called with a `ServerLoadEvent`, which inherits `clientAddress`, `cookies`, `locals`, `platform` and `request` from `RequestEvent`.
 
diff --git a/documentation/docs/50-reference/20-cli.md b/documentation/docs/50-reference/20-cli.md
index 46a0f81e6..d365c446f 100644
--- a/documentation/docs/50-reference/20-cli.md
+++ b/documentation/docs/50-reference/20-cli.md
@@ -12,4 +12,4 @@ However SvelteKit includes its own CLI for initialising your project:
 
 ## svelte-kit sync
 
-`svelte-kit sync` creates the generated files for your project such as types and a `tsconfig.json`. When you create a new project, it is listed as the `prepare` script and will be run automatically as part of the npm lifecycle, so you should not ordinarily have to run this command.
+`svelte-kit sync` creates the `tsconfig.json` and all generated types (which you can import as `./$types` inside routing files) for your project. When you create a new project, it is listed as the `prepare` script and will be run automatically as part of the npm lifecycle, so you should not ordinarily have to run this command.
diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js
index 49a469806..772dfacaa 100755
--- a/packages/kit/src/cli.js
+++ b/packages/kit/src/cli.js
@@ -24,7 +24,7 @@ const prog = sade('svelte-kit').version(pkg.version);
 
 prog
 	.command('sync')
-	.describe('Synchronise generated files')
+	.describe('Synchronise generated type definitions')
 	.option('--mode', 'Specify a mode for loading environment variables', 'development')
 	.action(async ({ mode }) => {
 		if (!fs.existsSync('svelte.config.js')) {
@@ -35,7 +35,7 @@ prog
 		try {
 			const config = await load_config();
 			const sync = await import('./core/sync/sync.js');
-			await sync.all(config, mode);
+			await sync.all_types(config, mode);
 		} catch (error) {
 			handle_error(error);
 		}
diff --git a/packages/kit/src/core/sync/sync.js b/packages/kit/src/core/sync/sync.js
index c598607da..d99c3315a 100644
--- a/packages/kit/src/core/sync/sync.js
+++ b/packages/kit/src/core/sync/sync.js
@@ -51,7 +51,7 @@ export async function update(config, manifest_data, file) {
 }
 
 /**
- * Run sync.init and sync.update in series, returning the result from sync.update.
+ * Run sync.init and sync.create in series, returning the result from sync.create.
  * @param {import('types').ValidatedConfig} config
  * @param {string} mode The Vite mode
  */
@@ -60,6 +60,17 @@ export async function all(config, mode) {
 	return await create(config);
 }
 
+/**
+ * Run sync.init and then generate all type files.
+ * @param {import('types').ValidatedConfig} config
+ * @param {string} mode The Vite mode
+ */
+export async function all_types(config, mode) {
+	init(config, mode);
+	const manifest_data = create_manifest_data({ config });
+	await write_all_types(config, manifest_data);
+}
+
 /**
  * Regenerate server-internal.js in response to src/{app.html,error.html,service-worker.js} changing
  * @param {import('types').ValidatedConfig} config
diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js
index 9809d918c..007fb0d19 100644
--- a/packages/kit/src/core/sync/write_tsconfig.js
+++ b/packages/kit/src/core/sync/write_tsconfig.js
@@ -35,19 +35,48 @@ function remove_trailing_slashstar(file) {
 
 /**
  * Writes the tsconfig that the user's tsconfig inherits from.
- * @param {import('types').ValidatedKitConfig} config
+ * @param {import('types').ValidatedKitConfig} kit
  */
-export function write_tsconfig(config, cwd = process.cwd()) {
-	const out = path.join(config.outDir, 'tsconfig.json');
-	const user_file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json');
+export function write_tsconfig(kit, cwd = process.cwd()) {
+	const out = path.join(kit.outDir, 'tsconfig.json');
+
+	const user_config = load_user_tsconfig(cwd);
+	if (user_config) validate_user_config(kit, cwd, out, user_config);
+
+	// only specify baseUrl if a) the user doesn't specify their own baseUrl
+	// and b) they have non-relative paths. this causes problems with auto-imports,
+	// so we print a suggestion that they use relative paths instead
+	// TODO(v2): never include base URL, and skip the check below
+	let include_base_url = false;
+
+	if (user_config && !user_config.options.compilerOptions?.baseUrl) {
+		const non_relative_paths = new Set();
+		for (const paths of Object.values(user_config?.options.compilerOptions?.paths || {})) {
+			for (const path of paths) {
+				if (!path.startsWith('.')) non_relative_paths.add(path);
+			}
+		}
+
+		if (non_relative_paths.size) {
+			include_base_url = true;
 
-	if (user_file) validate(config, cwd, out, user_file);
+			console.log(colors.bold().yellow('Please replace non-relative compilerOptions.paths:\n'));
+
+			for (const path of non_relative_paths) {
+				console.log(`  - "${path}" -> "./${path}"`);
+			}
+
+			console.log(
+				'\nDoing so allows us to omit "baseUrl" — which causes problems with imports — from the generated tsconfig.json. See https://github.com/sveltejs/kit/pull/8437 for more information.'
+			);
+		}
+	}
 
 	/** @param {string} file */
-	const config_relative = (file) => posixify(path.relative(config.outDir, file));
+	const config_relative = (file) => posixify(path.relative(kit.outDir, file));
 
 	const include = ['ambient.d.ts', './types/**/$types.d.ts', config_relative('vite.config.ts')];
-	for (const dir of [config.files.routes, config.files.lib]) {
+	for (const dir of [kit.files.routes, kit.files.lib]) {
 		const relative = project_relative(path.dirname(dir));
 		include.push(config_relative(`${relative}/**/*.js`));
 		include.push(config_relative(`${relative}/**/*.ts`));
@@ -61,12 +90,12 @@ export function write_tsconfig(config, cwd = process.cwd()) {
 	include.push(config_relative(`${test_folder}/**/*.svelte`));
 
 	const exclude = [config_relative('node_modules/**'), './[!ambient.d.ts]**'];
-	if (path.extname(config.files.serviceWorker)) {
-		exclude.push(config_relative(config.files.serviceWorker));
+	if (path.extname(kit.files.serviceWorker)) {
+		exclude.push(config_relative(kit.files.serviceWorker));
 	} else {
-		exclude.push(config_relative(`${config.files.serviceWorker}.js`));
-		exclude.push(config_relative(`${config.files.serviceWorker}.ts`));
-		exclude.push(config_relative(`${config.files.serviceWorker}.d.ts`));
+		exclude.push(config_relative(`${kit.files.serviceWorker}.js`));
+		exclude.push(config_relative(`${kit.files.serviceWorker}.ts`));
+		exclude.push(config_relative(`${kit.files.serviceWorker}.d.ts`));
 	}
 
 	write_if_changed(
@@ -75,8 +104,8 @@ export function write_tsconfig(config, cwd = process.cwd()) {
 			{
 				compilerOptions: {
 					// generated options
-					baseUrl: config_relative('.'),
-					paths: get_tsconfig_paths(config),
+					baseUrl: include_base_url ? config_relative('.') : undefined,
+					paths: get_tsconfig_paths(kit, include_base_url),
 					rootDirs: [config_relative('.'), './types'],
 
 					// essential options
@@ -105,43 +134,56 @@ export function write_tsconfig(config, cwd = process.cwd()) {
 	);
 }
 
+/** @param {string} cwd */
+function load_user_tsconfig(cwd) {
+	const file = maybe_file(cwd, 'tsconfig.json') || maybe_file(cwd, 'jsconfig.json');
+
+	if (!file) return;
+
+	// we have to eval the file, since it's not parseable as JSON (contains comments)
+	const json = fs.readFileSync(file, 'utf-8');
+
+	return {
+		kind: path.basename(file),
+		options: (0, eval)(`(${json})`)
+	};
+}
+
 /**
- * @param {import('types').ValidatedKitConfig} config
+ * @param {import('types').ValidatedKitConfig} kit
  * @param {string} cwd
  * @param {string} out
- * @param {string} user_file
+ * @param {{ kind: string, options: any }} config
  */
-function validate(config, cwd, out, user_file) {
-	// we have to eval the file, since it's not parseable as JSON (contains comments)
-	const user_tsconfig_json = fs.readFileSync(user_file, 'utf-8');
-	const user_tsconfig = (0, eval)(`(${user_tsconfig_json})`);
-
+function validate_user_config(kit, cwd, out, config) {
 	// we need to check that the user's tsconfig extends the framework config
-	const extend = user_tsconfig.extends;
+	const extend = config.options.extends;
 	const extends_framework_config = extend && path.resolve(cwd, extend) === out;
 
-	const kind = path.basename(user_file);
+	const options = config.options.compilerOptions || {};
 
 	if (extends_framework_config) {
-		const { paths: user_paths } = user_tsconfig.compilerOptions || {};
+		const { paths: user_paths } = options;
 
-		if (user_paths && fs.existsSync(config.files.lib)) {
+		if (user_paths && fs.existsSync(kit.files.lib)) {
 			/** @type {string[]} */
 			const lib = user_paths['$lib'] || [];
 			/** @type {string[]} */
 			const lib_ = user_paths['$lib/*'] || [];
 
+			// TODO(v2): check needs to be adjusted when we remove the base path
 			const missing_lib_paths =
-				!lib.some((relative) => path.resolve(cwd, relative) === config.files.lib) ||
-				!lib_.some((relative) => path.resolve(cwd, relative) === path.join(config.files.lib, '/*'));
+				!lib.some((relative) => path.resolve(cwd, relative) === kit.files.lib) ||
+				!lib_.some((relative) => path.resolve(cwd, relative) === path.join(kit.files.lib, '/*'));
 
 			if (missing_lib_paths) {
 				console.warn(
 					colors
 						.bold()
-						.yellow(`Your compilerOptions.paths in ${kind} should include the following:`)
+						.yellow(`Your compilerOptions.paths in ${config.kind} should include the following:`)
 				);
-				const relative = posixify(path.relative('.', config.files.lib));
+				let relative = posixify(path.relative('.', kit.files.lib));
+				if (!relative.startsWith('.')) relative = `./${relative}`;
 				console.warn(`{\n  "$lib":["${relative}"],\n  "$lib/*":["${relative}/*"]\n}`);
 			}
 		}
@@ -150,7 +192,9 @@ function validate(config, cwd, out, user_file) {
 		if (!relative.startsWith('./')) relative = './' + relative;
 
 		console.warn(
-			colors.bold().yellow(`Your ${kind} should extend the configuration generated by SvelteKit:`)
+			colors
+				.bold()
+				.yellow(`Your ${config.kind} should extend the configuration generated by SvelteKit:`)
 		);
 		console.warn(`{\n  "extends": "${relative}"\n}`);
 	}
@@ -166,11 +210,13 @@ const value_regex = /^(.*?)((\/\*)|(\.\w+))?$/;
  * Related to vite alias creation.
  *
  * @param {import('types').ValidatedKitConfig} config
+ * @param {boolean} include_base_url
  */
-export function get_tsconfig_paths(config) {
-	const alias = {
-		...config.alias
-	};
+export function get_tsconfig_paths(config, include_base_url) {
+	/** @param {string} file */
+	const config_relative = (file) => posixify(path.relative(config.outDir, file));
+
+	const alias = { ...config.alias };
 	if (fs.existsSync(project_relative(config.files.lib))) {
 		alias['$lib'] = project_relative(config.files.lib);
 	}
@@ -185,7 +231,9 @@ export function get_tsconfig_paths(config) {
 		const value_match = value_regex.exec(value);
 		if (!value_match) throw new Error(`Invalid alias value: ${value}`);
 
-		const rel_path = project_relative(remove_trailing_slashstar(value));
+		const rel_path = (include_base_url ? project_relative : config_relative)(
+			remove_trailing_slashstar(value)
+		);
 		const slashstar = key_match[2];
 
 		if (slashstar) {
diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js
index ec98438bb..530c32da7 100644
--- a/packages/kit/src/core/sync/write_tsconfig.spec.js
+++ b/packages/kit/src/core/sync/write_tsconfig.spec.js
@@ -4,7 +4,7 @@ import { validate_config } from '../config/index.js';
 import { get_tsconfig_paths } from './write_tsconfig.js';
 
 test('Creates tsconfig path aliases from kit.alias', () => {
-	const config = validate_config({
+	const { kit } = validate_config({
 		kit: {
 			alias: {
 				simpleKey: 'simple/value',
@@ -13,8 +13,35 @@ test('Creates tsconfig path aliases from kit.alias', () => {
 				keyToFile: 'path/to/file.ts'
 			}
 		}
-	}).kit;
-	const paths = get_tsconfig_paths(config);
+	});
+
+	const paths = get_tsconfig_paths(kit, false);
+
+	// $lib isn't part of the outcome because there's a "path exists"
+	// check in the implementation
+	assert.equal(paths, {
+		simpleKey: ['../simple/value'],
+		'simpleKey/*': ['../simple/value/*'],
+		key: ['../value'],
+		'key/*': ['../some/other/value/*'],
+		keyToFile: ['../path/to/file.ts']
+	});
+});
+
+test('Creates tsconfig path aliases from kit.alias with existing baseUrl', () => {
+	const { kit } = validate_config({
+		kit: {
+			alias: {
+				simpleKey: 'simple/value',
+				key: 'value',
+				'key/*': 'some/other/value/*',
+				keyToFile: 'path/to/file.ts'
+			}
+		}
+	});
+
+	const paths = get_tsconfig_paths(kit, true);
+
 	// $lib isn't part of the outcome because there's a "path exists"
 	// check in the implementation
 	assert.equal(paths, {
@@ -25,3 +52,5 @@ test('Creates tsconfig path aliases from kit.alias', () => {
 		keyToFile: ['path/to/file.ts']
 	});
 });
+
+test.run();
diff --git a/packages/kit/src/exports/index.js b/packages/kit/src/exports/index.js
index 63326a7fb..f5ba4abcf 100644
--- a/packages/kit/src/exports/index.js
+++ b/packages/kit/src/exports/index.js
@@ -48,8 +48,3 @@ export function json(data, init) {
 export function fail(status, data) {
 	return new ActionFailure(status, data);
 }
-
-// TODO remove for 1.0
-export function invalid() {
-	throw new Error('invalid(...) is now fail(...)');
-}
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index 9924fd438..1891ec283 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -1044,7 +1044,7 @@ export interface ServerLoadEvent<
 
 /**
  * Shape of a form action method that is part of `export const actions = {..}` in `+page.server.js`.
- * See [form actions](https://kit-svelte-d4b3r0pff-svelte.vercel.app/docs/form-actions) for more information.
+ * See [form actions](https://kit.svelte.dev/docs/form-actions) for more information.
  */
 export interface Action<
 	Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
@@ -1056,7 +1056,7 @@ export interface Action<
 
 /**
  * Shape of the `export const actions = {..}` object in `+page.server.js`.
- * See [form actions](https://kit-svelte-d4b3r0pff-svelte.vercel.app/docs/form-actions) for more information.
+ * See [form actions](https://kit.svelte.dev/docs/form-actions) for more information.
  */
 export type Actions<
 	Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,


Test patch:
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index 3f33bf33f..e71c8db88 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -370,7 +370,7 @@ test.describe('a11y', () => {
 		await page.goto('/keepfocus');
 
 		await Promise.all([
-			page.type('#input', 'bar'),
+			page.locator('#input').fill('bar'),
 			page.waitForFunction(() => window.location.search === '?foo=bar')
 		]);
 		await expect(page.locator('#input')).toBeFocused();
@@ -1156,12 +1156,12 @@ test.describe('data-sveltekit attributes', () => {
 		page.on('request', (r) => requests.push(r.url()));
 
 		await page.goto('/data-sveltekit/reload');
-		await page.locator('#one').click();
+		await clicknav('#one');
 		expect(requests).toContain(`${baseURL}/data-sveltekit/reload/target`);
 
 		requests.length = 0;
 		await page.goto('/data-sveltekit/reload');
-		await page.locator('#two').click();
+		await clicknav('#two');
 		expect(requests).toContain(`${baseURL}/data-sveltekit/reload/target`);
 
 		requests.length = 0;