@sveltejs/kit 2.15.2 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,9 +15,9 @@ import { build_server_nodes } from './build/build_server.js';
15
15
  import { build_service_worker } from './build/build_service_worker.js';
16
16
  import { assets_base, find_deps } from './build/utils.js';
17
17
  import { dev } from './dev/index.js';
18
- import { is_illegal, module_guard, normalize_id } from './graph_analysis/index.js';
18
+ import { is_illegal, module_guard } from './graph_analysis/index.js';
19
19
  import { preview } from './preview/index.js';
20
- import { get_config_aliases, get_env, strip_virtual_prefix } from './utils.js';
20
+ import { get_config_aliases, get_env, normalize_id, strip_virtual_prefix } from './utils.js';
21
21
  import { write_client_manifest } from '../../core/sync/write_client_manifest.js';
22
22
  import prerender from '../../core/postbuild/prerender.js';
23
23
  import analyse from '../../core/postbuild/analyse.js';
@@ -376,8 +376,14 @@ async function kit({ svelte_config }) {
376
376
  parsed_importer.name === parsed_service_worker.name;
377
377
 
378
378
  if (importer_is_service_worker && id !== '$service-worker' && id !== '$env/static/public') {
379
+ const normalized_cwd = vite.normalizePath(cwd);
380
+ const normalized_lib = vite.normalizePath(kit.files.lib);
379
381
  throw new Error(
380
- `Cannot import ${id} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
382
+ `Cannot import ${normalize_id(
383
+ id,
384
+ normalized_lib,
385
+ normalized_cwd
386
+ )} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
381
387
  );
382
388
  }
383
389
 
@@ -385,7 +391,11 @@ async function kit({ svelte_config }) {
385
391
  }
386
392
 
387
393
  // treat $env/static/[public|private] as virtual
388
- if (id.startsWith('$env/') || id.startsWith('__sveltekit/') || id === '$service-worker') {
394
+ if (id.startsWith('$env/') || id === '$service-worker') {
395
+ // ids with :$ don't work with reverse proxies like nginx
396
+ return `\0virtual:${id.substring(1)}`;
397
+ }
398
+ if (id.startsWith('__sveltekit/')) {
389
399
  return `\0virtual:${id}`;
390
400
  }
391
401
  },
@@ -649,7 +659,7 @@ async function kit({ svelte_config }) {
649
659
  format: inline ? 'iife' : 'esm',
650
660
  name: `__sveltekit_${version_hash}.app`,
651
661
  entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].${ext}`,
652
- chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name].[hash].${ext}`,
662
+ chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[hash].${ext}`,
653
663
  assetFileNames: `${prefix}/assets/[name].[hash][extname]`,
654
664
  hoistTransitiveImports: false,
655
665
  sourcemapIgnoreList,
@@ -666,7 +676,7 @@ async function kit({ svelte_config }) {
666
676
  rollupOptions: {
667
677
  output: {
668
678
  entryFileNames: `${prefix}/workers/[name]-[hash].js`,
669
- chunkFileNames: `${prefix}/workers/chunks/[name]-[hash].js`,
679
+ chunkFileNames: `${prefix}/workers/chunks/[hash].js`,
670
680
  assetFileNames: `${prefix}/workers/assets/[name]-[hash][extname]`,
671
681
  hoistTransitiveImports: false
672
682
  }
@@ -1,11 +1,11 @@
1
1
  import { fileURLToPath } from 'node:url';
2
2
 
3
- export const env_static_private = '\0virtual:$env/static/private';
4
- export const env_static_public = '\0virtual:$env/static/public';
5
- export const env_dynamic_private = '\0virtual:$env/dynamic/private';
6
- export const env_dynamic_public = '\0virtual:$env/dynamic/public';
3
+ export const env_static_private = '\0virtual:env/static/private';
4
+ export const env_static_public = '\0virtual:env/static/public';
5
+ export const env_dynamic_private = '\0virtual:env/dynamic/private';
6
+ export const env_dynamic_public = '\0virtual:env/dynamic/public';
7
7
 
8
- export const service_worker = '\0virtual:$service-worker';
8
+ export const service_worker = '\0virtual:service-worker';
9
9
 
10
10
  export const sveltekit_environment = '\0virtual:__sveltekit/environment';
11
11
  export const sveltekit_paths = '\0virtual:__sveltekit/paths';
@@ -4,6 +4,14 @@ import { posixify } from '../../utils/filesystem.js';
4
4
  import { negotiate } from '../../utils/http.js';
5
5
  import { filter_private_env, filter_public_env } from '../../utils/env.js';
6
6
  import { escape_html } from '../../utils/escape.js';
7
+ import {
8
+ app_server,
9
+ env_dynamic_private,
10
+ env_dynamic_public,
11
+ env_static_private,
12
+ env_static_public,
13
+ service_worker
14
+ } from './module_ids.js';
7
15
 
8
16
  /**
9
17
  * Transforms kit.alias to a valid vite.resolve.alias array.
@@ -105,4 +113,46 @@ export function not_found(req, res, base) {
105
113
  }
106
114
  }
107
115
 
116
+ /**
117
+ * Removes cwd/lib path from the start of the id
118
+ * @param {string} id
119
+ * @param {string} lib
120
+ * @param {string} cwd
121
+ */
122
+ export function normalize_id(id, lib, cwd) {
123
+ if (id.startsWith(lib)) {
124
+ id = id.replace(lib, '$lib');
125
+ }
126
+
127
+ if (id.startsWith(cwd)) {
128
+ id = path.relative(cwd, id);
129
+ }
130
+
131
+ if (id === app_server) {
132
+ return '$app/server';
133
+ }
134
+
135
+ if (id === env_static_private) {
136
+ return '$env/static/private';
137
+ }
138
+
139
+ if (id === env_static_public) {
140
+ return '$env/static/public';
141
+ }
142
+
143
+ if (id === env_dynamic_private) {
144
+ return '$env/dynamic/private';
145
+ }
146
+
147
+ if (id === env_dynamic_public) {
148
+ return '$env/dynamic/public';
149
+ }
150
+
151
+ if (id === service_worker) {
152
+ return '$service-worker';
153
+ }
154
+
155
+ return posixify(id);
156
+ }
157
+
108
158
  export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');
@@ -65,6 +65,9 @@ function clone(element) {
65
65
  * - redirects to the nearest error page in case of an unexpected error
66
66
  *
67
67
  * If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback.
68
+ * It accepts an options object
69
+ * - `reset: false` if you don't want the `<form>` values to be reset after a successful submission
70
+ * - `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission
68
71
  * @template {Record<string, unknown> | undefined} Success
69
72
  * @template {Record<string, unknown> | undefined} Failure
70
73
  * @param {HTMLFormElement} form_element The form element
@@ -8,13 +8,7 @@ import {
8
8
  make_trackable,
9
9
  normalize_path
10
10
  } from '../../utils/url.js';
11
- import {
12
- initial_fetch,
13
- lock_fetch,
14
- native_fetch,
15
- subsequent_fetch,
16
- unlock_fetch
17
- } from './fetcher.js';
11
+ import { dev_fetch, initial_fetch, lock_fetch, subsequent_fetch, unlock_fetch } from './fetcher.js';
18
12
  import { parse } from './parse.js';
19
13
  import * as storage from './session-storage.js';
20
14
  import {
@@ -312,7 +306,9 @@ export async function start(_app, _target, hydrate) {
312
306
  if (hydrate) {
313
307
  await _hydrate(target, hydrate);
314
308
  } else {
315
- goto(location.href, { replaceState: true });
309
+ goto(app.hash ? decode_hash(new URL(location.href)) : location.href, {
310
+ replaceState: true
311
+ });
316
312
  }
317
313
 
318
314
  _start_router();
@@ -380,7 +376,7 @@ function persist_state() {
380
376
 
381
377
  /**
382
378
  * @param {string | URL} url
383
- * @param {{ replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; state?: Record<string, any> }} options
379
+ * @param {{ replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; invalidate?: Array<string | URL | ((url: URL) => boolean)>; state?: Record<string, any> }} options
384
380
  * @param {number} redirect_count
385
381
  * @param {{}} [nav_token]
386
382
  */
@@ -398,6 +394,10 @@ async function _goto(url, options, redirect_count, nav_token) {
398
394
  if (options.invalidateAll) {
399
395
  force_invalidation = true;
400
396
  }
397
+
398
+ if (options.invalidate) {
399
+ options.invalidate.forEach(push_invalidated);
400
+ }
401
401
  }
402
402
  });
403
403
  }
@@ -428,9 +428,15 @@ async function _preload_data(intent) {
428
428
  return load_cache.promise;
429
429
  }
430
430
 
431
- /** @param {URL} url */
431
+ /**
432
+ * @param {URL} url
433
+ * @returns {Promise<void>}
434
+ */
432
435
  async function _preload_code(url) {
433
- const route = routes.find((route) => route.exec(get_url_path(url)));
436
+ const rerouted = get_rerouted_url(url);
437
+ if (!rerouted) return;
438
+
439
+ const route = routes.find((route) => route.exec(get_url_path(rerouted)));
434
440
 
435
441
  if (route) {
436
442
  await Promise.all([...route.layouts, route.leaf].map((load) => load?.[1]()));
@@ -1153,45 +1159,49 @@ async function load_root_error_page({ status, error, url, route }) {
1153
1159
  }
1154
1160
  }
1155
1161
 
1156
- const root_layout = await load_node({
1157
- loader: default_layout_loader,
1158
- url,
1159
- params,
1160
- route,
1161
- parent: () => Promise.resolve({}),
1162
- server_data_node: create_data_node(server_data_node)
1163
- });
1162
+ try {
1163
+ const root_layout = await load_node({
1164
+ loader: default_layout_loader,
1165
+ url,
1166
+ params,
1167
+ route,
1168
+ parent: () => Promise.resolve({}),
1169
+ server_data_node: create_data_node(server_data_node)
1170
+ });
1164
1171
 
1165
- /** @type {import('./types.js').BranchNode} */
1166
- const root_error = {
1167
- node: await default_error_loader(),
1168
- loader: default_error_loader,
1169
- universal: null,
1170
- server: null,
1171
- data: null
1172
- };
1172
+ /** @type {import('./types.js').BranchNode} */
1173
+ const root_error = {
1174
+ node: await default_error_loader(),
1175
+ loader: default_error_loader,
1176
+ universal: null,
1177
+ server: null,
1178
+ data: null
1179
+ };
1173
1180
 
1174
- return get_navigation_result_from_branch({
1175
- url,
1176
- params,
1177
- branch: [root_layout, root_error],
1178
- status,
1179
- error,
1180
- route: null
1181
- });
1181
+ return get_navigation_result_from_branch({
1182
+ url,
1183
+ params,
1184
+ branch: [root_layout, root_error],
1185
+ status,
1186
+ error,
1187
+ route: null
1188
+ });
1189
+ } catch (error) {
1190
+ if (error instanceof Redirect) {
1191
+ return _goto(new URL(error.location, location.href), {}, 0);
1192
+ }
1193
+
1194
+ // TODO: this falls back to the server when a server exists, but what about SPA mode?
1195
+ throw error;
1196
+ }
1182
1197
  }
1183
1198
 
1184
1199
  /**
1185
- * Resolve the full info (which route, params, etc.) for a client-side navigation from the URL,
1186
- * taking the reroute hook into account. If this isn't a client-side-navigation (or the URL is undefined),
1187
- * returns undefined.
1188
- * @param {URL | undefined} url
1189
- * @param {boolean} invalidating
1200
+ * Resolve the relative rerouted URL for a client-side navigation
1201
+ * @param {URL} url
1202
+ * @returns {URL | undefined}
1190
1203
  */
1191
- function get_navigation_intent(url, invalidating) {
1192
- if (!url) return;
1193
- if (is_external_url(url, base, app.hash)) return;
1194
-
1204
+ function get_rerouted_url(url) {
1195
1205
  // reroute could alter the given URL, so we pass a copy
1196
1206
  let rerouted;
1197
1207
  try {
@@ -1218,9 +1228,26 @@ function get_navigation_intent(url, invalidating) {
1218
1228
  }
1219
1229
 
1220
1230
  // fall back to native navigation
1221
- return undefined;
1231
+ return;
1222
1232
  }
1223
1233
 
1234
+ return rerouted;
1235
+ }
1236
+
1237
+ /**
1238
+ * Resolve the full info (which route, params, etc.) for a client-side navigation from the URL,
1239
+ * taking the reroute hook into account. If this isn't a client-side-navigation (or the URL is undefined),
1240
+ * returns undefined.
1241
+ * @param {URL | undefined} url
1242
+ * @param {boolean} invalidating
1243
+ */
1244
+ function get_navigation_intent(url, invalidating) {
1245
+ if (!url) return;
1246
+ if (is_external_url(url, base, app.hash)) return;
1247
+
1248
+ const rerouted = get_rerouted_url(url);
1249
+ if (!rerouted) return;
1250
+
1224
1251
  const path = get_url_path(rerouted);
1225
1252
 
1226
1253
  for (const route of routes) {
@@ -1802,6 +1829,7 @@ export function disableScrollHandling() {
1802
1829
  * @param {boolean} [opts.noScroll] If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
1803
1830
  * @param {boolean} [opts.keepFocus] If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
1804
1831
  * @param {boolean} [opts.invalidateAll] If `true`, all `load` functions of the page will be rerun. See https://svelte.dev/docs/kit/load#rerunning-load-functions for more info on invalidation.
1832
+ * @param {Array<string | URL | ((url: URL) => boolean)>} [opts.invalidate] Causes any load functions to re-run if they depend on one of the urls
1805
1833
  * @param {App.PageState} [opts.state] An optional object that will be available as `page.state`
1806
1834
  * @returns {Promise<void>}
1807
1835
  */
@@ -1848,14 +1876,21 @@ export function invalidate(resource) {
1848
1876
  throw new Error('Cannot call invalidate(...) on the server');
1849
1877
  }
1850
1878
 
1879
+ push_invalidated(resource);
1880
+
1881
+ return _invalidate();
1882
+ }
1883
+
1884
+ /**
1885
+ * @param {string | URL | ((url: URL) => boolean)} resource The invalidated URL
1886
+ */
1887
+ function push_invalidated(resource) {
1851
1888
  if (typeof resource === 'function') {
1852
1889
  invalidated.push(resource);
1853
1890
  } else {
1854
1891
  const { href } = new URL(resource, location.href);
1855
1892
  invalidated.push((url) => url.href === href);
1856
1893
  }
1857
-
1858
- return _invalidate();
1859
1894
  }
1860
1895
 
1861
1896
  /**
@@ -1927,13 +1962,20 @@ export function preloadCode(pathname) {
1927
1962
  const url = new URL(pathname, current.url);
1928
1963
 
1929
1964
  if (DEV) {
1965
+ if (!pathname.startsWith('/')) {
1966
+ throw new Error(
1967
+ 'argument passed to preloadCode must be a pathname (i.e. "/about" rather than "http://example.com/about"'
1968
+ );
1969
+ }
1970
+
1930
1971
  if (!pathname.startsWith(base)) {
1931
1972
  throw new Error(
1932
- `pathnames passed to preloadCode must start with \`paths.base\` (i.e. "${base}${pathname}" rather than "${pathname}")`
1973
+ `pathname passed to preloadCode must start with \`paths.base\` (i.e. "${base}${pathname}" rather than "${pathname}")`
1933
1974
  );
1934
1975
  }
1935
1976
 
1936
- if (!routes.find((route) => route.exec(get_url_path(url)))) {
1977
+ const rerouted = get_rerouted_url(url);
1978
+ if (!rerouted || !routes.find((route) => route.exec(get_url_path(rerouted)))) {
1937
1979
  throw new Error(`'${pathname}' did not match any routes`);
1938
1980
  }
1939
1981
  }
@@ -2321,7 +2363,7 @@ function _start_router() {
2321
2363
  const state = event.state[STATES_KEY] ?? {};
2322
2364
  const url = new URL(event.state[PAGE_URL_KEY] ?? location.href);
2323
2365
  const navigation_index = event.state[NAVIGATION_INDEX];
2324
- const is_hash_change = strip_hash(location) === strip_hash(current.url);
2366
+ const is_hash_change = current.url ? strip_hash(location) === strip_hash(current.url) : false;
2325
2367
  const shallow =
2326
2368
  navigation_index === current_navigation_index && (has_navigated || is_hash_change);
2327
2369
 
@@ -2392,7 +2434,7 @@ function _start_router() {
2392
2434
  // (surprisingly!) mutates `current.url`, allowing us to
2393
2435
  // detect it and trigger a navigation
2394
2436
  if (current.url.hash === location.hash) {
2395
- navigate({ type: 'goto', url: current.url });
2437
+ navigate({ type: 'goto', url: decode_hash(current.url) });
2396
2438
  }
2397
2439
  }
2398
2440
  });
@@ -2539,7 +2581,9 @@ async function load_data(url, invalid) {
2539
2581
  }
2540
2582
  data_url.searchParams.append(INVALIDATED_PARAM, invalid.map((i) => (i ? '1' : '0')).join(''));
2541
2583
 
2542
- const res = await native_fetch(data_url.href);
2584
+ // use window.fetch directly to allow using a 3rd party-patched fetch implementation
2585
+ const fetcher = DEV ? dev_fetch : window.fetch;
2586
+ const res = await fetcher(data_url.href, {});
2543
2587
 
2544
2588
  if (!res.ok) {
2545
2589
  // error message is a JSON-stringified string which devalue can't handle at the top level
@@ -2784,6 +2828,17 @@ function clone_page(page) {
2784
2828
  };
2785
2829
  }
2786
2830
 
2831
+ /**
2832
+ * @param {URL} url
2833
+ * @returns {URL}
2834
+ */
2835
+ function decode_hash(url) {
2836
+ const new_url = new URL(url);
2837
+ // Safari, for some reason, does change # to %23, when entered through the address bar
2838
+ new_url.hash = decodeURIComponent(url.hash);
2839
+ return new_url;
2840
+ }
2841
+
2787
2842
  if (DEV) {
2788
2843
  // Nasty hack to silence harmless warnings the user can do nothing about
2789
2844
  const console_warn = console.warn;
@@ -5,7 +5,7 @@ import { b64_decode } from '../utils.js';
5
5
  let loading = 0;
6
6
 
7
7
  /** @type {typeof fetch} */
8
- export const native_fetch = BROWSER ? window.fetch : /** @type {any} */ (() => {});
8
+ const native_fetch = BROWSER ? window.fetch : /** @type {any} */ (() => {});
9
9
 
10
10
  export function lock_fetch() {
11
11
  loading += 1;
@@ -137,7 +137,7 @@ export function subsequent_fetch(resource, resolved, opts) {
137
137
  * @param {RequestInfo | URL} resource
138
138
  * @param {RequestInit & Record<string, any> | undefined} opts
139
139
  */
140
- function dev_fetch(resource, opts) {
140
+ export function dev_fetch(resource, opts) {
141
141
  const patched_opts = { ...opts };
142
142
  // This assigns the __sveltekit_fetch__ flag and makes it non-enumerable
143
143
  Object.defineProperty(patched_opts, '__sveltekit_fetch__', {
@@ -311,7 +311,7 @@ export function is_external_url(url, base, hash_routing) {
311
311
  }
312
312
 
313
313
  if (hash_routing) {
314
- if (url.pathname === base + '/') {
314
+ if (url.pathname === base + '/' || url.pathname === base + '/index.html') {
315
315
  return false;
316
316
  }
317
317
 
@@ -55,7 +55,7 @@ export function get_cookies(request, url, trailing_slash) {
55
55
 
56
56
  /**
57
57
  * @param {string} name
58
- * @param {import('cookie').CookieParseOptions} opts
58
+ * @param {import('cookie').CookieParseOptions} [opts]
59
59
  */
60
60
  get(name, opts) {
61
61
  const c = new_cookies[name];
@@ -91,7 +91,7 @@ export function get_cookies(request, url, trailing_slash) {
91
91
  },
92
92
 
93
93
  /**
94
- * @param {import('cookie').CookieParseOptions} opts
94
+ * @param {import('cookie').CookieParseOptions} [opts]
95
95
  */
96
96
  getAll(opts) {
97
97
  const cookies = parse(header, { decode: opts?.decode });
@@ -1,3 +1,4 @@
1
+ import { DEV } from 'esm-env';
1
2
  import { ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
2
3
  import { negotiate } from '../../utils/http.js';
3
4
  import { Redirect } from '../control.js';
@@ -10,6 +11,10 @@ import { method_not_allowed } from './utils.js';
10
11
  * @returns {Promise<Response>}
11
12
  */
12
13
  export async function render_endpoint(event, mod, state) {
14
+ if (DEV && event.request.headers.get('x-sveltekit-action') === 'true') {
15
+ throw new Error('use:enhance should only be used with SvelteKit form actions');
16
+ }
17
+
13
18
  const method = /** @type {import('types').HttpMethod} */ (event.request.method);
14
19
 
15
20
  let handler = mod[method] || mod.fallback;
@@ -85,6 +85,21 @@ export async function respond(request, options, manifest, state) {
85
85
  return text('Not found', { status: 404 });
86
86
  }
87
87
 
88
+ const is_data_request = has_data_suffix(url.pathname);
89
+ /** @type {boolean[] | undefined} */
90
+ let invalidated_data_nodes;
91
+ if (is_data_request) {
92
+ url.pathname =
93
+ strip_data_suffix(url.pathname) +
94
+ (url.searchParams.get(TRAILING_SLASH_PARAM) === '1' ? '/' : '') || '/';
95
+ url.searchParams.delete(TRAILING_SLASH_PARAM);
96
+ invalidated_data_nodes = url.searchParams
97
+ .get(INVALIDATED_PARAM)
98
+ ?.split('')
99
+ .map((node) => node === '1');
100
+ url.searchParams.delete(INVALIDATED_PARAM);
101
+ }
102
+
88
103
  // reroute could alter the given URL, so we pass a copy
89
104
  let rerouted_path;
90
105
  try {
@@ -126,22 +141,6 @@ export async function respond(request, options, manifest, state) {
126
141
  return text('Not found', { status: 404, headers });
127
142
  }
128
143
 
129
- const is_data_request = has_data_suffix(decoded);
130
- /** @type {boolean[] | undefined} */
131
- let invalidated_data_nodes;
132
- if (is_data_request) {
133
- decoded = strip_data_suffix(decoded) || '/';
134
- url.pathname =
135
- strip_data_suffix(url.pathname) +
136
- (url.searchParams.get(TRAILING_SLASH_PARAM) === '1' ? '/' : '') || '/';
137
- url.searchParams.delete(TRAILING_SLASH_PARAM);
138
- invalidated_data_nodes = url.searchParams
139
- .get(INVALIDATED_PARAM)
140
- ?.split('')
141
- .map((node) => node === '1');
142
- url.searchParams.delete(INVALIDATED_PARAM);
143
- }
144
-
145
144
  if (!state.prerendering?.fallback) {
146
145
  // TODO this could theoretically break — should probably be inside a try-catch
147
146
  const matchers = await manifest._.matchers();
@@ -4,17 +4,22 @@ import { pathToFileURL } from 'node:url';
4
4
 
5
5
  /**
6
6
  * Resolve a dependency relative to the current working directory,
7
- * rather than relative to this package
7
+ * rather than relative to this package (but falls back to trying that, if necessary)
8
8
  * @param {string} dependency
9
9
  */
10
- export function resolve_peer_dependency(dependency) {
10
+ export async function resolve_peer_dependency(dependency) {
11
11
  try {
12
12
  // @ts-expect-error the types are wrong
13
13
  const resolved = imr.resolve(dependency, pathToFileURL(process.cwd() + '/dummy.js'));
14
- return import(resolved);
14
+ return await import(resolved);
15
15
  } catch {
16
- throw new Error(
17
- `Could not resolve peer dependency "${dependency}" relative to your project please install it and try again.`
18
- );
16
+ try {
17
+ // both imr.resolve and await import above can throw, which is why we can't just do import(resolved).catch(...) above
18
+ return await import(dependency);
19
+ } catch {
20
+ throw new Error(
21
+ `Could not resolve peer dependency "${dependency}" relative to your project — please install it and try again.`
22
+ );
23
+ }
19
24
  }
20
25
  }
@@ -1,5 +1,4 @@
1
- // @ts-ignore - need to publish types for sub-package imports
2
- import BROWSER from 'esm-env/browser';
1
+ import { BROWSER } from 'esm-env';
3
2
 
4
3
  const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
5
4
 
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // generated during release, do not modify
2
2
 
3
3
  /** @type {string} */
4
- export const VERSION = '2.15.2';
4
+ export const VERSION = '2.16.0';