Repository: sveltejs/kit
Pull request #9536 (2023-03-27 18:54:42)

chore(deps): update pnpm to v7.30.5
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [pnpm](https://pnpm.io) ([source](https://togithub.com/pnpm/pnpm)) | [`7.30.3` -> `7.30.5`](https://renovatebot.com/diffs/npm/pnpm/7.30.3/7.30.5) | [![age](https://badges.renovateapi.com/packages/npm/pnpm/7.30.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/pnpm/7.30.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/pnpm/7.30.5/compatibility-slim/7.30.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/pnpm/7.30.5/confidence-slim/7.30.3)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>pnpm/pnpm</summary>

### [`v7.30.5`](https://togithub.com/pnpm/pnpm/releases/tag/v7.30.5)

[Compare Source](https://togithub.com/pnpm/pnpm/compare/v7.30.4...v7.30.5)

#### Patch Changes

-   `pnpm audit` should work even if there are no `package.json` file, just a `pnpm-lock.yaml` file.
-   Dedupe direct dependencies after hoisting.
-   Don't remove automatically installed peer dependencies from the root workspace project, when `dedupe-peer-dependents` is `true` [#&#8203;6154](https://togithub.com/pnpm/pnpm/issues/6154).

#### Our Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://novu.co/?utm_source=pnpm&utm_medium=release_notes" target="_blank">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/novu.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/novu_light.svg" />
            <img src="https://pnpm.io/img/users/novu.svg" width="180" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://prisma.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/prisma.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/prisma_light.svg" />
            <img src="https://pnpm.io/img/users/prisma.svg" width="180" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.flightcontrol.dev/?ref=pnpm" target="_blank"><img src="https://pnpm.io/img/users/flightcontrol.png" width="240"></a>
      </td>
    </tr>
  </tbody>
</table>

#### Our Silver Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://leniolabs.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank">
          <img src="https://pnpm.io/img/users/leniolabs.jpg" width="80">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vercel.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/vercel.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/vercel_light.svg" />
            <img src="https://pnpm.io/img/users/vercel.svg" width="180" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://depot.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/depot.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/depot_light.svg" />
            <img src="https://pnpm.io/img/users/depot.svg" width="200" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

### [`v7.30.4`](https://togithub.com/pnpm/pnpm/compare/v7.30.3...v7.30.4)

[Compare Source](https://togithub.com/pnpm/pnpm/compare/v7.30.3...v7.30.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/sveltejs/kit).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4yMi4xIiwidXBkYXRlZEluVmVyIjoiMzUuMjIuMSJ9-->


changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 904d061b18983e0ecf91511cf5e992143db4d2c6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/sveltejs/kit/new/renovate/all-minor-patch?filename=.changeset/moody-tigers-change.md&value=---%0A%0A---%0A%0Achore(deps)%3A%20update%20pnpm%20to%20v7.30.5%0A)



Patch:
diff --git a/.changeset/sharp-trainers-search.md b/.changeset/sharp-trainers-search.md
new file mode 100644
index 000000000..0d143f8a4
--- /dev/null
+++ b/.changeset/sharp-trainers-search.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: make `error.message` enumerable when sending `ssrLoadModule` error to client
diff --git a/.changeset/sharp-wolves-march.md b/.changeset/sharp-wolves-march.md
new file mode 100644
index 000000000..64aa30be2
--- /dev/null
+++ b/.changeset/sharp-wolves-march.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: pass `publicDir` Vite config in SSR
diff --git a/.changeset/stupid-trains-push.md b/.changeset/stupid-trains-push.md
new file mode 100644
index 000000000..58f77cd1c
--- /dev/null
+++ b/.changeset/stupid-trains-push.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': minor
+---
+
+feat: expose stronger typed `SubmitFunction` through `./$types`
diff --git a/package.json b/package.json
index 23c7c32b4..83923a0ee 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
 		"tiny-glob": "^0.2.9",
 		"typescript": "^4.9.4"
 	},
-	"packageManager": "pnpm@7.30.3",
+	"packageManager": "pnpm@7.30.5",
 	"engines": {
 		"pnpm": "^7.0.0"
 	},
diff --git a/packages/kit/src/core/sync/write_types/index.js b/packages/kit/src/core/sync/write_types/index.js
index 0ae180492..c1e0c827c 100644
--- a/packages/kit/src/core/sync/write_types/index.js
+++ b/packages/kit/src/core/sync/write_types/index.js
@@ -390,16 +390,23 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true
 
 		if (is_page) {
 			let type = 'unknown';
-			if (proxy) {
-				if (proxy.exports.includes('actions')) {
-					// If the file wasn't tweaked, we can use the return type of the original file.
-					// The advantage is that type updates are reflected without saving.
-					const from = proxy.modified
-						? `./proxy${replace_ext_with_js(basename)}`
-						: path_to_original(outdir, node.server);
-
-					type = `Expand<Kit.AwaitedActions<typeof import('${from}').actions>> | null`;
-				}
+			if (proxy && proxy.exports.includes('actions')) {
+				// If the file wasn't tweaked, we can use the return type of the original file.
+				// The advantage is that type updates are reflected without saving.
+				const from = proxy.modified
+					? `./proxy${replace_ext_with_js(basename)}`
+					: path_to_original(outdir, node.server);
+
+				exports.push(
+					`type ExcludeActionFailure<T> = T extends Kit.ActionFailure<any> ? never : T extends void ? never : T;`,
+					`type ActionsSuccess<T extends Record<string, (...args: any) => any>> = { [Key in keyof T]: ExcludeActionFailure<Awaited<ReturnType<T[Key]>>>; }[keyof T];`,
+					`type ExtractActionFailure<T> = T extends Kit.ActionFailure<infer X>	? X extends void ? never : X : never;`,
+					`type ActionsFailure<T extends Record<string, (...args: any) => any>> = { [Key in keyof T]: Exclude<ExtractActionFailure<Awaited<ReturnType<T[Key]>>>, void>; }[keyof T];`,
+					`type ActionsExport = typeof import('${from}').actions`,
+					`export type SubmitFunction = Kit.SubmitFunction<Expand<ActionsSuccess<ActionsExport>>, Expand<ActionsFailure<ActionsExport>>>`
+				);
+
+				type = `Expand<Kit.AwaitedActions<ActionsExport>> | null`;
 			}
 			exports.push(`export type ActionData = ${type};`);
 		}
diff --git a/packages/kit/src/core/sync/write_types/index.spec.js b/packages/kit/src/core/sync/write_types/index.spec.js
index 5abb42c66..1971a959f 100644
--- a/packages/kit/src/core/sync/write_types/index.spec.js
+++ b/packages/kit/src/core/sync/write_types/index.spec.js
@@ -33,6 +33,7 @@ test('Creates correct $types', async () => {
 	// To safe us from creating a real SvelteKit project for each of the tests,
 	// we first run the type generation directly for each test case, and then
 	// call `tsc` to check that the generated types are valid.
+	await run_test('actions');
 	await run_test('simple-page-shared-only');
 	await run_test('simple-page-server-only');
 	await run_test('simple-page-server-and-shared');
diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js
index 1addb038e..d279e488c 100644
--- a/packages/kit/src/exports/vite/dev/index.js
+++ b/packages/kit/src/exports/vite/dev/index.js
@@ -58,7 +58,16 @@ export async function dev(vite, vite_config, svelte_config) {
 			const msg = buildErrorMessage(err, [colors.red(`Internal server error: ${err.message}`)]);
 
 			vite.config.logger.error(msg, { error: err });
-			vite.ws.send({ type: 'error', err: err });
+			vite.ws.send({
+				type: 'error',
+				err: {
+					...err,
+					// these properties are non-enumerable and will
+					// not be serialized unless we explicitly include them
+					message: err.message,
+					stack: err.stack
+				}
+			});
 
 			throw err;
 		}
diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js
index 028d873e3..c2a339693 100644
--- a/packages/kit/src/exports/vite/index.js
+++ b/packages/kit/src/exports/vite/index.js
@@ -564,11 +564,12 @@ function kit({ svelte_config }) {
 							preserveEntrySignatures: 'strict'
 						},
 						ssrEmitAssets: true,
+						copyPublicDir: !ssr,
 						target: ssr ? 'node16.14' : undefined,
 						// don't use the default name to avoid collisions with 'static/manifest.json'
 						manifest: 'vite-manifest.json'
 					},
-					publicDir: ssr ? false : kit.files.assets,
+					publicDir: kit.files.assets,
 					worker: {
 						rollupOptions: {
 							output: {
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index c2019c4e2..19d6c8424 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -1167,10 +1167,10 @@ export type Actions<
  */
 export type ActionResult<
 	Success extends Record<string, unknown> | undefined = Record<string, any>,
-	Invalid extends Record<string, unknown> | undefined = Record<string, any>
+	Failure extends Record<string, unknown> | undefined = Record<string, any>
 > =
 	| { type: 'success'; status: number; data?: Success }
-	| { type: 'failure'; status: number; data?: Invalid }
+	| { type: 'failure'; status: number; data?: Failure }
 	| { type: 'redirect'; status: number; location: string }
 	| { type: 'error'; status?: number; error: any };
 
@@ -1239,7 +1239,7 @@ export function text(body: string, init?: ResponseInit): Response;
  * @param status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
  * @param data Data associated with the failure (e.g. validation errors)
  */
-export function fail<T extends Record<string, unknown> | undefined>(
+export function fail<T extends Record<string, unknown> | undefined = undefined>(
 	status: number,
 	data?: T
 ): ActionFailure<T>;
@@ -1257,7 +1257,7 @@ export interface ActionFailure<T extends Record<string, unknown> | undefined = u
 
 export interface SubmitFunction<
 	Success extends Record<string, unknown> | undefined = Record<string, any>,
-	Invalid extends Record<string, unknown> | undefined = Record<string, any>
+	Failure extends Record<string, unknown> | undefined = Record<string, any>
 > {
 	(input: {
 		action: URL;
@@ -1271,7 +1271,7 @@ export interface SubmitFunction<
 		| ((opts: {
 				form: HTMLFormElement;
 				action: URL;
-				result: ActionResult<Success, Invalid>;
+				result: ActionResult<Success, Failure>;
 				/**
 				 * Call this to get the default behavior of a form submission response.
 				 * @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission.


Test patch:
diff --git a/packages/kit/src/core/sync/write_types/test/actions/+page.server.js b/packages/kit/src/core/sync/write_types/test/actions/+page.server.js
new file mode 100644
index 000000000..46dd8f8f4
--- /dev/null
+++ b/packages/kit/src/core/sync/write_types/test/actions/+page.server.js
@@ -0,0 +1,87 @@
+import { fail } from '../../../../../../types/internal.js';
+
+let condition = false;
+
+export const actions = {
+	default: () => {
+		if (condition) {
+			return fail(400, {
+				fail: 'oops'
+			});
+		}
+
+		return {
+			success: true
+		};
+	},
+	successWithPayload: () => {
+		return {
+			id: 42,
+			username: 'John Doe',
+			profession: 'Svelte specialist'
+		};
+	},
+	successWithoutPayload: () => {},
+	failWithPayload: () => {
+		return fail(400, {
+			reason: {
+				error: {
+					code: /** @type {const} */ ('VALIDATION_FAILED')
+				}
+			}
+		});
+	},
+	failWithoutPayload: () => {
+		return fail(400);
+	}
+};
+
+/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/actions/$types').SubmitFunction} */
+const submit = () => {
+	return ({ result }) => {
+		if (result.type === 'success') {
+			// @ts-expect-error does only exist on `failure` result
+			result.data?.fail;
+			// @ts-expect-error unknown property
+			result.data?.something;
+
+			if (result.data && 'success' in result.data) {
+				result.data.success === true;
+				// @ts-expect-error should be of type `boolean`
+				result.data.success === 'success';
+				// @ts-expect-error does not exist in this branch
+				result.data.id;
+			}
+
+			if (result.data && 'id' in result.data) {
+				result.data.id === 42;
+				// @ts-expect-error should be of type `number`
+				result.data.id === 'John';
+				// @ts-expect-error does not exist in this branch
+				result.data.success;
+			}
+		}
+
+		if (result.type === 'failure') {
+			result.data;
+			// @ts-expect-error does only exist on `success` result
+			result.data.success;
+			// @ts-expect-error unknown property
+			result.data.unknown;
+
+			if (result.data && 'fail' in result.data) {
+				result.data.fail === '';
+				// @ts-expect-error does not exist in this branch
+				result.data.reason;
+			}
+
+			if (result.data && 'reason' in result.data) {
+				result.data.reason.error.code === 'VALIDATION_FAILED';
+				// @ts-expect-error should be a const
+				result.data.reason.error.code === '';
+				// @ts-expect-error does not exist in this branch
+				result.data.fail;
+			}
+		}
+	};
+};