@sveltejs/kit 3.0.0-next.6 → 3.0.0-next.7

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.
Files changed (64) hide show
  1. package/package.json +7 -2
  2. package/src/core/adapt/builder.js +11 -39
  3. package/src/core/config/index.js +76 -71
  4. package/src/core/config/options.js +280 -285
  5. package/src/core/config/types.d.ts +1 -1
  6. package/src/core/env.js +85 -1
  7. package/src/core/generate_manifest/index.js +12 -15
  8. package/src/core/sync/create_manifest_data/index.js +6 -44
  9. package/src/core/sync/write_client_manifest.js +7 -14
  10. package/src/core/sync/write_non_ambient.js +10 -7
  11. package/src/core/sync/write_root.js +9 -30
  12. package/src/core/sync/write_server.js +0 -1
  13. package/src/core/sync/write_types/index.js +11 -10
  14. package/src/exports/index.js +3 -3
  15. package/src/exports/internal/client.js +5 -0
  16. package/src/exports/internal/index.js +1 -91
  17. package/src/exports/internal/{event.js → server/event.js} +1 -2
  18. package/src/exports/internal/server/index.js +33 -0
  19. package/src/exports/internal/shared.js +89 -0
  20. package/src/exports/node/index.js +1 -1
  21. package/src/exports/params.js +63 -0
  22. package/src/exports/public.d.ts +82 -32
  23. package/src/exports/url.js +84 -0
  24. package/src/exports/vite/dev/index.js +28 -17
  25. package/src/exports/vite/index.js +217 -156
  26. package/src/exports/vite/preview/index.js +1 -1
  27. package/src/exports/vite/utils.js +3 -5
  28. package/src/runtime/app/paths/client.js +3 -7
  29. package/src/runtime/app/paths/server.js +1 -1
  30. package/src/runtime/app/server/remote/query.js +6 -12
  31. package/src/runtime/app/state/client.js +1 -2
  32. package/src/runtime/app/stores.js +13 -76
  33. package/src/runtime/client/client.js +26 -79
  34. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  35. package/src/runtime/client/remote-functions/form.svelte.js +5 -24
  36. package/src/runtime/client/remote-functions/prerender.svelte.js +10 -3
  37. package/src/runtime/client/remote-functions/query/instance.svelte.js +18 -9
  38. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +16 -6
  39. package/src/runtime/client/remote-functions/shared.svelte.js +1 -2
  40. package/src/runtime/client/state.svelte.js +66 -49
  41. package/src/runtime/client/types.d.ts +1 -1
  42. package/src/runtime/client/utils.js +0 -96
  43. package/src/runtime/form-utils.js +15 -2
  44. package/src/runtime/server/index.js +1 -1
  45. package/src/runtime/server/page/load_data.js +1 -1
  46. package/src/runtime/server/page/render.js +15 -24
  47. package/src/runtime/server/page/server_routing.js +13 -9
  48. package/src/runtime/server/remote.js +21 -12
  49. package/src/runtime/server/respond.js +11 -8
  50. package/src/runtime/telemetry/otel.js +1 -1
  51. package/src/types/ambient.d.ts +5 -1
  52. package/src/types/global-private.d.ts +1 -1
  53. package/src/types/internal.d.ts +9 -10
  54. package/src/utils/error.js +1 -1
  55. package/src/utils/mime.js +9 -0
  56. package/src/utils/params.js +66 -0
  57. package/src/utils/routing.js +84 -38
  58. package/src/utils/streaming.js +14 -4
  59. package/src/utils/url.js +0 -79
  60. package/src/version.js +1 -1
  61. package/types/index.d.ts +98 -87
  62. package/types/index.d.ts.map +10 -7
  63. package/src/exports/internal/server.js +0 -22
  64. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
package/src/core/env.js CHANGED
@@ -94,8 +94,9 @@ export async function load_explicit_env(kit, file, root, mode) {
94
94
  * @param {Record<string, EnvVarConfig<any> | undefined> | null} variables
95
95
  * @param {Record<string, string>} env
96
96
  * @param {string | null} entry
97
+ * @param {boolean} is_dev
97
98
  */
98
- export function create_sveltekit_env(variables, env, entry) {
99
+ export function create_sveltekit_env(variables, env, entry, is_dev) {
99
100
  const imports = entry
100
101
  ? [
101
102
  `import { variables } from ${JSON.stringify(entry)};`,
@@ -149,6 +150,19 @@ export function create_sveltekit_env(variables, env, entry) {
149
150
  }`
150
151
  ];
151
152
 
153
+ // In dev, initialise the env immediately. Tools like `vite-node` load modules
154
+ // through the Vite config but don't run the SvelteKit dev server, which is what
155
+ // normally calls `set_env`. Without this, dynamic env vars imported from
156
+ // `$app/env/public` and `$app/env/private` would be `undefined` in such contexts.
157
+ if (is_dev) {
158
+ /** @type {Record<string, string>} */
159
+ const dev_env = {};
160
+ for (const name of Object.keys(variables ?? {})) {
161
+ if (name in env) dev_env[name] = env[name];
162
+ }
163
+ blocks.push(`set_env(${devalue.uneval(dev_env)});`);
164
+ }
165
+
152
166
  const module = blocks.join('\n\n');
153
167
 
154
168
  return module;
@@ -361,3 +375,73 @@ export const reserved = new Set([
361
375
  ]);
362
376
 
363
377
  export const valid_identifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
378
+
379
+ /**
380
+ * Generates `export const` declarations (and, for reserved-word names that need
381
+ * aliasing, `const` + re-export specifiers) for a set of named exports.
382
+ *
383
+ * For regular names, emits a single efficient `export const name = expr;` statement.
384
+ * For reserved-word names (e.g. `delete`, `class`), emits `const alias = expr;` plus
385
+ * a re-export specifier (`alias as name`), since reserved words can't be `const`
386
+ * binding names but CAN appear in export specifiers.
387
+ *
388
+ * You can do evil things like `export { c as class }`. In order to import/re-export
389
+ * these, you need to alias the binding, then un-alias it when re-exporting:
390
+ *
391
+ * const _0 = ...; // safe binding name
392
+ * export { _0 as class }; // valid — `class` is allowed in export specifiers
393
+ *
394
+ * Aliases are chosen to avoid collisions with any of the supplied names. The
395
+ * namespace binding (used to hold the imported module) is likewise chosen to
396
+ * avoid collisions.
397
+ *
398
+ * @param {Iterable<string>} names — the export names
399
+ * @param {(name: string, namespace: string) => string} build_expression —
400
+ * called for each name to produce the right-hand side of the declaration;
401
+ * receives the chosen namespace binding so it can reference the imported module
402
+ * @param {string} namespace_prefix — the preferred binding name for the namespace
403
+ * (suffixed with a number if it collides with any export name)
404
+ * @returns {{ namespace: string, declarations: string[], reexports: string[] }}
405
+ */
406
+ export function create_exported_declarations(names, build_expression, namespace_prefix) {
407
+ /** @type {Set<string>} */
408
+ const set = new Set(names);
409
+
410
+ let namespace = namespace_prefix;
411
+ let namespace_index = 0;
412
+ while (set.has(namespace)) {
413
+ namespace = `${namespace_prefix}${namespace_index++}`;
414
+ }
415
+
416
+ let alias_index = 0;
417
+ /** @type {Map<string, string>} */
418
+ const aliases = new Map();
419
+
420
+ for (const name of set) {
421
+ if (!reserved.has(name)) continue;
422
+
423
+ let alias = `_${alias_index++}`;
424
+ while (set.has(alias)) {
425
+ alias = `_${alias_index++}`;
426
+ }
427
+ aliases.set(name, alias);
428
+ }
429
+
430
+ /** @type {string[]} */
431
+ const declarations = [];
432
+ /** @type {string[]} */
433
+ const reexports = [];
434
+
435
+ for (const name of set) {
436
+ const alias = aliases.get(name);
437
+ const expr = build_expression(name, namespace);
438
+ if (alias) {
439
+ declarations.push(`const ${alias} = ${expr};`);
440
+ reexports.push(`${alias} as ${name}`);
441
+ } else {
442
+ declarations.push(`export const ${name} = ${expr};`);
443
+ }
444
+ }
445
+
446
+ return { namespace, declarations, reexports };
447
+ }
@@ -1,7 +1,7 @@
1
1
  /** @import { RemoteChunk } from 'types' */
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
- import * as mime from 'mrmime';
4
+ import { lookup as mime_lookup } from '../../utils/mime.js';
5
5
  import { s } from '../../utils/misc.js';
6
6
  import { get_mime_lookup } from '../utils.js';
7
7
  import { resolve_symlinks } from '../../exports/vite/build/utils.js';
@@ -69,10 +69,8 @@ export function generate_manifest({
69
69
  assets.push(build_data.service_worker);
70
70
  }
71
71
 
72
- // In case of server-side route resolution, we need to include all matchers. Prerendered routes are not part
73
- // of the server manifest, and they could reference matchers that then would not be included.
74
- const matchers = new Set(
75
- build_data.client?.nodes ? Object.keys(build_data.manifest_data.matchers) : undefined
72
+ const uses_matchers = build_data.manifest_data.routes.some((route) =>
73
+ route.params.some((param) => param.matcher)
76
74
  );
77
75
 
78
76
  /** @param {Array<number | undefined>} indexes */
@@ -93,7 +91,7 @@ export function generate_manifest({
93
91
  files[file] = fs.statSync(path.resolve(build_data.out_dir, 'server', file)).size;
94
92
 
95
93
  const ext = path.extname(file);
96
- mime_types[ext] ??= mime.lookup(ext) || '';
94
+ mime_types[ext] ??= mime_lookup(ext) || '';
97
95
  }
98
96
 
99
97
  // prettier-ignore
@@ -117,10 +115,6 @@ export function generate_manifest({
117
115
  ${routes.map(route => {
118
116
  if (!route.page && !route.endpoint) return;
119
117
 
120
- route.params.forEach(param => {
121
- if (param.matcher) matchers.add(param.matcher);
122
- });
123
-
124
118
  return dedent`
125
119
  {
126
120
  id: ${s(route.id)},
@@ -134,11 +128,14 @@ export function generate_manifest({
134
128
  ],
135
129
  prerendered_routes: new Set(${s(prerendered)}),
136
130
  matchers: async () => {
137
- ${Array.from(
138
- matchers,
139
- type => `const { match: ${type} } = await import ('${(join_relative(relative_path, `/entries/matchers/${type}.js`))}')`
140
- ).join('\n')}
141
- return { ${Array.from(matchers).join(', ')} };
131
+ ${
132
+ uses_matchers && build_data.manifest_data.params
133
+ ? dedent`
134
+ const { params } = await import('${join_relative(relative_path, '/entries/params.js')}');
135
+ return params;
136
+ `
137
+ : 'return {};'
138
+ }
142
139
  },
143
140
  server_assets: ${s(files)}
144
141
  }
@@ -1,4 +1,4 @@
1
- import { lookup } from 'mrmime';
1
+ import { lookup } from '../../../utils/mime.js';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { styleText } from 'node:util';
@@ -29,22 +29,13 @@ export default function create_manifest_data({
29
29
  }) {
30
30
  const assets = create_assets(config);
31
31
  const hooks = create_hooks(config, cwd);
32
- const matchers = create_matchers(config, cwd);
32
+ const params = resolve_params(config, cwd);
33
33
  const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback);
34
34
 
35
- // validate matcher names used in parameterised routes
36
- for (const route of routes) {
37
- for (const param of route.params) {
38
- if (param.matcher && !matchers[param.matcher]) {
39
- throw new Error(`No matcher found for parameter '${param.matcher}' in route ${route.id}`);
40
- }
41
- }
42
- }
43
-
44
35
  return {
45
36
  assets,
46
37
  hooks,
47
- matchers,
38
+ params,
48
39
  nodes,
49
40
  routes
50
41
  };
@@ -82,38 +73,9 @@ function create_hooks(config, cwd) {
82
73
  * @param {import('types').ValidatedConfig} config
83
74
  * @param {string} cwd
84
75
  */
85
- function create_matchers(config, cwd) {
86
- const params_base = path.relative(cwd, config.kit.files.params);
87
-
88
- /** @type {Record<string, string>} */
89
- const matchers = {};
90
- if (fs.existsSync(config.kit.files.params)) {
91
- for (const file of fs.readdirSync(config.kit.files.params)) {
92
- const ext = path.extname(file);
93
- if (!config.kit.moduleExtensions.includes(ext)) continue;
94
- const type = file.slice(0, -ext.length);
95
-
96
- if (/^\w+$/.test(type)) {
97
- const matcher_file = path.join(params_base, file);
98
-
99
- // Disallow same matcher with different extensions
100
- if (matchers[type]) {
101
- throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`);
102
- } else {
103
- matchers[type] = matcher_file;
104
- }
105
- } else {
106
- // Allow for matcher test collocation
107
- if (type.endsWith('.test') || type.endsWith('.spec')) continue;
108
-
109
- throw new Error(
110
- `Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid`
111
- );
112
- }
113
- }
114
- }
115
-
116
- return matchers;
76
+ function resolve_params(config, cwd) {
77
+ const params_file = resolve_entry(config.kit.files.params);
78
+ return params_file ? posixify(path.relative(cwd, params_file)) : null;
117
79
  }
118
80
 
119
81
  /**
@@ -188,21 +188,14 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
188
188
  );
189
189
 
190
190
  if (client_routing) {
191
- // write matchers to a separate module so that we don't
192
- // need to worry about name conflicts
193
- const imports = [];
194
- const matchers = [];
195
-
196
- for (const key in manifest_data.matchers) {
197
- const src = manifest_data.matchers[key];
198
-
199
- imports.push(`import { match as ${key} } from ${s(relative_path(output, src))};`);
200
- matchers.push(key);
201
- }
191
+ const uses_matchers = manifest_data.routes.some((route) =>
192
+ route.params.some((param) => param.matcher)
193
+ );
202
194
 
203
- const module = imports.length
204
- ? `${imports.join('\n')}\n\nexport const matchers = { ${matchers.join(', ')} };`
205
- : 'export const matchers = {};';
195
+ const module =
196
+ !manifest_data.params || !uses_matchers
197
+ ? 'export const matchers = {};'
198
+ : `import { params as matchers } from ${s(relative_path(output, manifest_data.params))};\n\nexport { matchers };`;
206
199
 
207
200
  write_if_changed(`${output}/matchers.js`, module);
208
201
  }
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { GENERATED_COMMENT } from '../../constants.js';
3
+ import { resolve_entry } from '../../utils/filesystem.js';
3
4
  import { posixify } from '../../utils/os.js';
4
5
  import { write_if_changed } from './utils.js';
5
6
  import { s } from '../../utils/misc.js';
@@ -85,10 +86,6 @@ export {};
85
86
  * @param {import('types').ValidatedKitConfig} config
86
87
  */
87
88
  function generate_app_types(manifest_data, config) {
88
- /** @param {string} matcher */
89
- const path_to_matcher = (matcher) =>
90
- posixify(path.relative(config.outDir, path.join(config.files.params, matcher + '.js')));
91
-
92
89
  /** @type {Map<string, string>} */
93
90
  const matcher_types = new Map();
94
91
 
@@ -98,7 +95,15 @@ function generate_app_types(manifest_data, config) {
98
95
 
99
96
  let type = matcher_types.get(matcher);
100
97
  if (!type) {
101
- type = `MatcherParam<typeof import('${path_to_matcher(matcher)}').match>`;
98
+ const path_to_params = () => {
99
+ const params_file =
100
+ resolve_entry(config.files.params) ??
101
+ config.files.params.replace(/\.(js|ts)$/, '') + '.js';
102
+
103
+ return posixify(path.relative(config.outDir, params_file));
104
+ };
105
+
106
+ type = `import('@sveltejs/kit').MatcherParam<(typeof import('${path_to_params()}').params)[${JSON.stringify(matcher)}]>`;
102
107
  matcher_types.set(matcher, type);
103
108
  }
104
109
 
@@ -239,8 +244,6 @@ function generate_app_types(manifest_data, config) {
239
244
 
240
245
  return [
241
246
  'declare module "$app/types" {',
242
- '\ttype MatcherParam<M> = M extends (param : string) => param is (infer U extends string) ? U : string;',
243
- '',
244
247
  '\texport interface AppTypes {',
245
248
  `\t\tRouteId(): ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
246
249
  `\t\tRouteParams(): {\n\t\t\t${dynamic_routes.join(';\n\t\t\t')}\n\t\t};`,
@@ -81,45 +81,24 @@ export function write_root(manifest_data, config, output) {
81
81
  <!-- This file is generated by @sveltejs/kit — do not edit it! -->
82
82
  <svelte:options runes={true} />
83
83
  <script>
84
- import { setContext, onMount, tick } from 'svelte';
85
- import { browser } from '$app/env';
84
+ import { afterNavigate } from '$app/navigation';
86
85
 
87
- // stores
88
- let { stores, page, constructors, components = [], form, ${use_boundaries ? 'errors = [], error, ' : ''}${levels
86
+ let { page, constructors, components = [], form, ${use_boundaries ? 'errors = [], error, ' : ''}${levels
89
87
  .map((l) => `data_${l} = null`)
90
88
  .join(', ')} } = $props();
91
89
  ${use_boundaries ? `let data = $derived({${levels.map((l) => `'${l}': data_${l}`).join(', ')}})` : ''}
92
90
 
93
- if (browser) {
94
- $effect.pre(() => stores.page.set(page));
95
- } else {
96
- // svelte-ignore state_referenced_locally
97
- setContext('__svelte__', stores);
98
- // svelte-ignore state_referenced_locally
99
- stores.page.set(page);
100
- }
101
-
102
- $effect(() => {
103
- stores;page;constructors;components;form;${use_boundaries ? 'errors;error;' : ''}${levels.map((l) => `data_${l}`).join(';')};
104
- stores.page.notify();
105
- });
106
-
107
91
  let mounted = $state(false);
108
92
  let navigated = $state(false);
109
93
  let title = $state(null);
110
94
 
111
- onMount(() => {
112
- const unsubscribe = stores.page.subscribe(() => {
113
- if (mounted) {
114
- navigated = true;
115
- tick().then(() => {
116
- title = document.title || 'untitled page';
117
- });
118
- }
119
- });
120
-
121
- mounted = true;
122
- return unsubscribe;
95
+ afterNavigate(() => {
96
+ if (mounted) {
97
+ navigated = true;
98
+ title = document.title || 'untitled page';
99
+ } else {
100
+ mounted = true;
101
+ }
123
102
  });
124
103
 
125
104
  const Pyramid_${max_depth} = $derived(constructors[${max_depth}]);
@@ -32,7 +32,6 @@ import error from '../shared/error-template.js';
32
32
 
33
33
  export const options = {
34
34
  app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
35
- async: ${s(!!config.compilerOptions?.experimental?.async)},
36
35
  csp: ${s(config.kit.csp)},
37
36
  csrf_check_origin: ${s(!config.kit.csrf.trustedOrigins.includes('*'))},
38
37
  csrf_trusted_origins: ${s(config.kit.csrf.trustedOrigins)},
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import MagicString from 'magic-string';
4
- import { rimraf, walk } from '../../../utils/filesystem.js';
4
+ import { rimraf, walk, resolve_entry } from '../../../utils/filesystem.js';
5
5
  import { compact } from '../../../utils/array.js';
6
6
  import { posixify } from '../../../utils/os.js';
7
7
  import { ts } from '../ts.js';
@@ -198,11 +198,6 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
198
198
  // Makes sure a type is "repackaged" and therefore more readable
199
199
  declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
200
200
 
201
- // returns the predicate of a matcher's type guard - or string if there is no type guard
202
- declarations.push(
203
- 'type MatcherParam<M> = M extends (param : string) => param is (infer U extends string) ? U : string;'
204
- );
205
-
206
201
  declarations.push(
207
202
  'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';'
208
203
  );
@@ -604,16 +599,22 @@ function replace_ext_with_js(file_path) {
604
599
  * @param {import('types').ValidatedConfig} config
605
600
  */
606
601
  function generate_params_type(params, outdir, config) {
607
- /** @param {string} matcher */
608
- const path_to_matcher = (matcher) =>
609
- posixify(path.relative(outdir, path.join(config.kit.files.params, matcher + '.js')));
602
+ const path_to_params = () => {
603
+ const params_file =
604
+ resolve_entry(config.kit.files.params) ??
605
+ config.kit.files.params.replace(/\.(js|ts)$/, '') + '.js';
606
+
607
+ return posixify(path.relative(outdir, params_file));
608
+ };
609
+
610
+ const params_import = path_to_params();
610
611
 
611
612
  return `{ ${params
612
613
  .map(
613
614
  (param) =>
614
615
  `${param.name}${param.optional ? '?' : ''}: ${
615
616
  param.matcher
616
- ? `MatcherParam<typeof import('${path_to_matcher(param.matcher)}').match>`
617
+ ? `import('@sveltejs/kit').MatcherParam<(typeof import('${params_import}').params)[${JSON.stringify(param.matcher)}]>`
617
618
  : 'string'
618
619
  }${param.optional ? ' | undefined' : ''}`
619
620
  )
@@ -1,6 +1,5 @@
1
1
  /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
-
3
- import { HttpError, Redirect, ActionFailure, ValidationError } from './internal/index.js';
2
+ import { HttpError, Redirect, ActionFailure, ValidationError } from './internal/shared.js';
4
3
  import { BROWSER, DEV } from 'esm-env';
5
4
  import {
6
5
  add_data_suffix,
@@ -11,9 +10,10 @@ import {
11
10
  strip_resolution_suffix
12
11
  } from '../runtime/pathname.js';
13
12
  import { text_encoder } from '../runtime/utils.js';
14
- import { validate_redirect_location } from '../utils/url.js';
13
+ import { validate_redirect_location } from './url.js';
15
14
 
16
15
  export { VERSION } from '../version.js';
16
+ export { defineParams } from './params.js';
17
17
 
18
18
  // Keep the status codes as `number` because restricting to certain numbers makes it unnecessarily hard to use compared to the benefits
19
19
  // (we have runtime errors already to check for invalid codes). Also see https://github.com/sveltejs/kit/issues/11780
@@ -0,0 +1,5 @@
1
+ export function get_origin() {
2
+ return window.location.origin;
3
+ }
4
+
5
+ export * from './shared.js';
@@ -1,91 +1 @@
1
- /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
-
3
- export class HttpError {
4
- /**
5
- * @param {number} status
6
- * @param {Omit<App.Error, 'status'> | string | undefined} body
7
- * @param {Omit<App.Error, 'status' | 'message'>} [properties]
8
- */
9
- constructor(status, body, properties) {
10
- this.status = status;
11
- if (typeof body === 'string') {
12
- this.body = { ...properties, message: body, status };
13
- } else if (body) {
14
- this.body = { ...body, status };
15
- } else {
16
- this.body = { message: `Error: ${status}`, status };
17
- }
18
- }
19
-
20
- toString() {
21
- return JSON.stringify(this.body);
22
- }
23
- }
24
-
25
- export class Redirect {
26
- /**
27
- * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
28
- * @param {string} location
29
- */
30
- constructor(status, location) {
31
- try {
32
- new Headers({ location });
33
- } catch {
34
- throw new Error(
35
- `Invalid redirect location ${JSON.stringify(location)}: ` +
36
- 'this string contains characters that cannot be used in HTTP headers'
37
- );
38
- }
39
-
40
- this.status = status;
41
- this.location = location;
42
- }
43
- }
44
-
45
- /**
46
- * An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
47
- * `SvelteKitError` goes through `handleError`.
48
- * @extends Error
49
- */
50
- export class SvelteKitError extends Error {
51
- /**
52
- * @param {number} status
53
- * @param {string} text
54
- * @param {string} message
55
- */
56
- constructor(status, text, message) {
57
- super(message);
58
- this.status = status;
59
- this.text = text;
60
- }
61
- }
62
-
63
- /**
64
- * @template [T=undefined]
65
- */
66
- export class ActionFailure {
67
- /**
68
- * @param {number} status
69
- * @param {T} data
70
- */
71
- constructor(status, data) {
72
- this.status = status;
73
- this.data = data;
74
- }
75
- }
76
-
77
- /**
78
- * Error thrown when form validation fails imperatively
79
- */
80
- export class ValidationError extends Error {
81
- /**
82
- * @param {StandardSchemaV1.Issue[]} issues
83
- */
84
- constructor(issues) {
85
- super('Validation failed');
86
- this.name = 'ValidationError';
87
- this.issues = issues;
88
- }
89
- }
90
-
91
- export { init_remote_functions } from './remote-functions.js';
1
+ export * from '#internal';
@@ -1,8 +1,7 @@
1
1
  /** @import { RequestEvent } from '@sveltejs/kit' */
2
2
  /** @import { RequestStore } from 'types' */
3
3
  /** @import { AsyncLocalStorage } from 'node:async_hooks' */
4
-
5
- import { IN_WEBCONTAINER } from '../../runtime/server/constants.js';
4
+ import { IN_WEBCONTAINER } from '../../../runtime/server/constants.js';
6
5
 
7
6
  /** @type {RequestStore | null} */
8
7
  let sync_store = null;
@@ -0,0 +1,33 @@
1
+ /** @import { Span } from '@opentelemetry/api' */
2
+ import { try_get_request_store } from './event.js';
3
+
4
+ export function get_origin() {
5
+ return try_get_request_store()?.event.url.origin;
6
+ }
7
+
8
+ /**
9
+ * @template {{ tracing: { enabled: boolean, root: Span, current: Span } }} T
10
+ * @param {T} event_like
11
+ * @param {Span} current
12
+ * @returns {T}
13
+ */
14
+ export function merge_tracing(event_like, current) {
15
+ return {
16
+ ...event_like,
17
+ tracing: {
18
+ ...event_like.tracing,
19
+ current
20
+ }
21
+ };
22
+ }
23
+
24
+ export {
25
+ with_request_store,
26
+ getRequestEvent,
27
+ get_request_store,
28
+ try_get_request_store
29
+ } from './event.js';
30
+
31
+ export { init_remote_functions } from './remote-functions.js';
32
+
33
+ export * from '../shared.js';
@@ -0,0 +1,89 @@
1
+ /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
+
3
+ export class HttpError {
4
+ /**
5
+ * @param {number} status
6
+ * @param {Omit<App.Error, 'status'> | string | undefined} body
7
+ * @param {Omit<App.Error, 'status' | 'message'>} [properties]
8
+ */
9
+ constructor(status, body, properties) {
10
+ this.status = status;
11
+ if (typeof body === 'string') {
12
+ this.body = { ...properties, message: body, status };
13
+ } else if (body) {
14
+ this.body = { ...body, status };
15
+ } else {
16
+ this.body = { message: `Error: ${status}`, status };
17
+ }
18
+ }
19
+
20
+ toString() {
21
+ return JSON.stringify(this.body);
22
+ }
23
+ }
24
+
25
+ export class Redirect {
26
+ /**
27
+ * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
28
+ * @param {string} location
29
+ */
30
+ constructor(status, location) {
31
+ try {
32
+ new Headers({ location });
33
+ } catch {
34
+ throw new Error(
35
+ `Invalid redirect location ${JSON.stringify(location)}: ` +
36
+ 'this string contains characters that cannot be used in HTTP headers'
37
+ );
38
+ }
39
+
40
+ this.status = status;
41
+ this.location = location;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
47
+ * `SvelteKitError` goes through `handleError`.
48
+ * @extends Error
49
+ */
50
+ export class SvelteKitError extends Error {
51
+ /**
52
+ * @param {number} status
53
+ * @param {string} text
54
+ * @param {string} message
55
+ */
56
+ constructor(status, text, message) {
57
+ super(message);
58
+ this.status = status;
59
+ this.text = text;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @template [T=undefined]
65
+ */
66
+ export class ActionFailure {
67
+ /**
68
+ * @param {number} status
69
+ * @param {T} data
70
+ */
71
+ constructor(status, data) {
72
+ this.status = status;
73
+ this.data = data;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Error thrown when form validation fails imperatively
79
+ */
80
+ export class ValidationError extends Error {
81
+ /**
82
+ * @param {StandardSchemaV1.Issue[]} issues
83
+ */
84
+ constructor(issues) {
85
+ super('Validation failed');
86
+ this.name = 'ValidationError';
87
+ this.issues = issues;
88
+ }
89
+ }