Skip to content

Commit 6f6fa38

Browse files
breaking: remove resolvePath (#11265)
closes #10282 --------- Co-authored-by: Rich Harris <rich.harris@vercel.com> Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
1 parent 63ad25a commit 6f6fa38

File tree

12 files changed

+474
-426
lines changed

12 files changed

+474
-426
lines changed

.changeset/eighty-scissors-kick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': major
3+
---
4+
5+
breaking: remove `resolvePath` in favour of `resolveRoute` from `$app/paths`

documentation/docs/60-appendix/30-migrating-to-sveltekit-2.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,23 @@ This inconsistency is fixed in version 2. Paths are either always relative or al
9292

9393
Previously it was possible to track URLs from `fetch`es on the server in order to rerun load functions. This poses a possible security risk (private URLs leaking), and as such it was behind the `dangerZone.trackServerFetches` setting, which is now removed.
9494

95+
## `resolvePath` has been removed
96+
97+
SvelteKit 1 included a function called `resolvePath` which allows you to resolve a route ID (like `/blog/[slug]`) and a set of parameters (like `{ slug: 'hello' }`) to a pathname. Unfortunately the return value didn't include the `base` path, limiting its usefulness in cases where `base` was set.
98+
99+
As such, SvelteKit 2 replaces `resolvePath` with a (slightly better named) function called `resolveRoute`, which is imported from `$app/paths` and which takes `base` into account.
100+
101+
```diff
102+
-import { resolvePath } from '@sveltejs/kit';
103+
-import { base } from '$app/paths';
104+
+import { resolveRoute } from '$app/paths';
105+
106+
-const path = base + resolvePath('/blog/[slug]', { slug });
107+
+const path = resolveRoute('/blog/[slug]', { slug });
108+
```
109+
110+
`svelte-migrate` will do the method replacement for you, though if you later prepend the result with `base`, you need to remove that yourself.
111+
95112
## Updated dependency requirements
96113

97114
SvelteKit requires Node `18.13` or higher, Vite `^5.0`, vite-plugin-svelte `^3.0`, TypeScript `^5.0` and Svelte version 4 or higher. `svelte-migrate` will do the `package.json` bumps for you.

packages/kit/src/core/postbuild/analyse.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import {
1111
import { load_config } from '../config/index.js';
1212
import { forked } from '../../utils/fork.js';
1313
import { installPolyfills } from '../../exports/node/polyfills.js';
14-
import { resolvePath } from '../../exports/index.js';
1514
import { ENDPOINT_METHODS } from '../../constants.js';
1615
import { filter_private_env, filter_public_env } from '../../utils/env.js';
16+
import { resolve_route } from '../../utils/routing.js';
1717

1818
export default forked(import.meta.url, analyse);
1919

@@ -101,7 +101,7 @@ async function analyse({ manifest_path, env }) {
101101
},
102102
prerender: page?.prerender ?? endpoint?.prerender,
103103
entries:
104-
entries && (await entries()).map((entry_object) => resolvePath(route.id, entry_object))
104+
entries && (await entries()).map((entry_object) => resolve_route(route.id, entry_object))
105105
});
106106
}
107107

packages/kit/src/exports/index.js

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { HttpError, Redirect, ActionFailure } from '../runtime/control.js';
22
import { BROWSER, DEV } from 'esm-env';
3-
import { get_route_segments } from '../utils/routing.js';
43

54
export { VERSION } from '../version.js';
65

@@ -183,58 +182,3 @@ export function fail(status, data) {
183182
// @ts-expect-error unique symbol missing
184183
return new ActionFailure(status, data);
185184
}
186-
187-
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
188-
189-
let warned = false;
190-
191-
/**
192-
* @deprecated Use `resolveRoute` from `$app/paths` instead.
193-
*
194-
* Populate a route ID with params to resolve a pathname.
195-
* @example
196-
* ```js
197-
* resolvePath(
198-
* `/blog/[slug]/[...somethingElse]`,
199-
* {
200-
* slug: 'hello-world',
201-
* somethingElse: 'something/else'
202-
* }
203-
* ); // `/blog/hello-world/something/else`
204-
* ```
205-
* @param {string} id
206-
* @param {Record<string, string | undefined>} params
207-
* @returns {string}
208-
*/
209-
export function resolvePath(id, params) {
210-
if (!warned) {
211-
console.warn('`resolvePath` is deprecated. Use `resolveRoute` from `$app/paths` instead.');
212-
warned = true;
213-
}
214-
215-
const segments = get_route_segments(id);
216-
return (
217-
'/' +
218-
segments
219-
.map((segment) =>
220-
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
221-
const param_value = params[name];
222-
223-
// This is nested so TS correctly narrows the type
224-
if (!param_value) {
225-
if (optional) return '';
226-
if (rest && param_value !== undefined) return '';
227-
throw new Error(`Missing parameter '${name}' in route ${id}`);
228-
}
229-
230-
if (param_value.startsWith('/') || param_value.endsWith('/'))
231-
throw new Error(
232-
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
233-
);
234-
return param_value;
235-
})
236-
)
237-
.filter(Boolean)
238-
.join('/')
239-
);
240-
}

packages/kit/src/exports/index.spec.js

Lines changed: 0 additions & 59 deletions
This file was deleted.
Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
export { base, assets } from '__sveltekit/paths';
22
import { base } from '__sveltekit/paths';
3-
import { get_route_segments } from '../../utils/routing.js';
4-
5-
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
3+
import { resolve_route } from '../../utils/routing.js';
64

75
/**
86
* Populate a route ID with params to resolve a pathname.
@@ -21,30 +19,5 @@ const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
2119
* @returns {string}
2220
*/
2321
export function resolveRoute(id, params) {
24-
const segments = get_route_segments(id);
25-
return (
26-
base +
27-
'/' +
28-
segments
29-
.map((segment) =>
30-
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
31-
const param_value = params[name];
32-
33-
// This is nested so TS correctly narrows the type
34-
if (!param_value) {
35-
if (optional) return '';
36-
if (rest && param_value !== undefined) return '';
37-
throw new Error(`Missing parameter '${name}' in route ${id}`);
38-
}
39-
40-
if (param_value.startsWith('/') || param_value.endsWith('/'))
41-
throw new Error(
42-
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
43-
);
44-
return param_value;
45-
})
46-
)
47-
.filter(Boolean)
48-
.join('/')
49-
);
22+
return base + resolve_route(id, params);
5023
}

packages/kit/src/runtime/server/page/actions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as devalue from 'devalue';
2-
import { json } from '../../../exports/index.js';
2+
import { error, json } from '../../../exports/index.js';
33
import { normalize_error } from '../../../utils/error.js';
44
import { is_form_content_type, negotiate } from '../../../utils/http.js';
55
import { HttpError, Redirect, ActionFailure } from '../../control.js';

packages/kit/src/utils/routing.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,49 @@ function escape(str) {
214214
.replace(/[.*+?^${}()|\\]/g, '\\$&')
215215
);
216216
}
217+
218+
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
219+
220+
/**
221+
* Populate a route ID with params to resolve a pathname.
222+
* @example
223+
* ```js
224+
* resolveRoute(
225+
* `/blog/[slug]/[...somethingElse]`,
226+
* {
227+
* slug: 'hello-world',
228+
* somethingElse: 'something/else'
229+
* }
230+
* ); // `/blog/hello-world/something/else`
231+
* ```
232+
* @param {string} id
233+
* @param {Record<string, string | undefined>} params
234+
* @returns {string}
235+
*/
236+
export function resolve_route(id, params) {
237+
const segments = get_route_segments(id);
238+
return (
239+
'/' +
240+
segments
241+
.map((segment) =>
242+
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
243+
const param_value = params[name];
244+
245+
// This is nested so TS correctly narrows the type
246+
if (!param_value) {
247+
if (optional) return '';
248+
if (rest && param_value !== undefined) return '';
249+
throw new Error(`Missing parameter '${name}' in route ${id}`);
250+
}
251+
252+
if (param_value.startsWith('/') || param_value.endsWith('/'))
253+
throw new Error(
254+
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
255+
);
256+
return param_value;
257+
})
258+
)
259+
.filter(Boolean)
260+
.join('/')
261+
);
262+
}

0 commit comments

Comments
 (0)