@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21

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 (195) hide show
  1. package/package.json +62 -36
  2. package/src/cli.js +15 -12
  3. package/src/constants.js +6 -1
  4. package/src/core/adapt/builder.js +66 -72
  5. package/src/core/adapt/index.js +17 -6
  6. package/src/core/config/index.js +134 -80
  7. package/src/core/config/options.js +295 -273
  8. package/src/core/config/types.d.ts +1 -1
  9. package/src/core/env.js +146 -16
  10. package/src/core/generate_manifest/index.js +18 -15
  11. package/src/core/postbuild/analyse.js +8 -20
  12. package/src/core/postbuild/crawl.js +22 -6
  13. package/src/core/postbuild/entities.js +8 -2
  14. package/src/core/postbuild/fallback.js +4 -2
  15. package/src/core/postbuild/prerender.js +222 -70
  16. package/src/core/postbuild/queue.js +2 -1
  17. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  18. package/src/core/sync/create_manifest_data/index.js +82 -62
  19. package/src/core/sync/sync.js +40 -31
  20. package/src/core/sync/ts.js +1 -1
  21. package/src/core/sync/utils.js +22 -2
  22. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
  23. package/src/core/sync/write_client_manifest.js +14 -29
  24. package/src/core/sync/write_env.js +7 -5
  25. package/src/core/sync/write_server.js +37 -45
  26. package/src/core/sync/write_tsconfig/index.js +274 -0
  27. package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
  28. package/src/core/sync/write_tsconfig/utils.js +77 -0
  29. package/src/core/sync/write_tsconfig/validate.js +128 -0
  30. package/src/core/sync/write_types/index.js +127 -123
  31. package/src/core/utils.js +30 -5
  32. package/src/exports/env/index.js +77 -0
  33. package/src/exports/env/public.d.ts +55 -0
  34. package/src/exports/hooks/index.js +3 -9
  35. package/src/exports/hooks/public.d.ts +195 -0
  36. package/src/exports/hooks/sequence.js +9 -6
  37. package/src/exports/index.js +52 -29
  38. package/src/exports/internal/client.js +5 -0
  39. package/src/exports/internal/env.js +8 -5
  40. package/src/exports/internal/index.js +1 -90
  41. package/src/exports/internal/{event.js → server/event.js} +2 -3
  42. package/src/exports/internal/server/index.js +37 -0
  43. package/src/exports/internal/server/telemetry.js +95 -0
  44. package/src/exports/internal/shared.js +90 -0
  45. package/src/exports/node/index.js +64 -22
  46. package/src/exports/params/index.js +70 -0
  47. package/src/exports/params/public.d.ts +63 -0
  48. package/src/exports/public.d.ts +50 -1733
  49. package/src/exports/remote/index.js +11 -0
  50. package/src/exports/remote/public.d.ts +519 -0
  51. package/src/exports/url.js +86 -0
  52. package/src/exports/vite/build/build_server.js +54 -65
  53. package/src/exports/vite/build/remote.js +24 -19
  54. package/src/exports/vite/build/utils.js +0 -8
  55. package/src/exports/vite/dev/index.js +218 -146
  56. package/src/exports/vite/index.js +1590 -858
  57. package/src/exports/vite/module_ids.js +2 -2
  58. package/src/exports/vite/preview/index.js +40 -32
  59. package/src/exports/vite/public.d.ts +588 -0
  60. package/src/exports/vite/utils.js +84 -46
  61. package/src/pathname.js +55 -0
  62. package/src/runner.js +15 -0
  63. package/src/runtime/app/env/internal.js +4 -4
  64. package/src/runtime/app/env/types.d.ts +1 -1
  65. package/src/runtime/app/environment/index.js +3 -3
  66. package/src/runtime/app/{forms.js → forms/index.js} +73 -42
  67. package/src/runtime/app/forms/public.d.ts +2 -0
  68. package/src/runtime/app/forms/types.d.ts +56 -0
  69. package/src/runtime/app/internal/transport.js +53 -0
  70. package/src/runtime/app/manifest/index.js +1 -0
  71. package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
  72. package/src/runtime/app/navigation/public.d.ts +237 -0
  73. package/src/runtime/app/paths/client.js +37 -37
  74. package/src/runtime/app/paths/index.js +1 -1
  75. package/src/runtime/app/paths/internal/client.js +34 -2
  76. package/src/runtime/app/paths/internal/server.js +6 -23
  77. package/src/runtime/app/paths/internal.d.ts +3 -0
  78. package/src/runtime/app/paths/public.d.ts +1 -29
  79. package/src/runtime/app/paths/server.js +36 -17
  80. package/src/runtime/app/paths/types.d.ts +11 -19
  81. package/src/runtime/app/server/index.js +2 -2
  82. package/src/runtime/app/server/public.d.ts +201 -0
  83. package/src/runtime/app/server/remote/command.js +13 -11
  84. package/src/runtime/app/server/remote/form.js +61 -39
  85. package/src/runtime/app/server/remote/prerender.js +45 -45
  86. package/src/runtime/app/server/remote/query.js +106 -108
  87. package/src/runtime/app/server/remote/requested.js +27 -19
  88. package/src/runtime/app/server/remote/shared.js +76 -76
  89. package/src/runtime/app/service-worker/index.js +24 -0
  90. package/src/runtime/app/state/client.js +4 -2
  91. package/src/runtime/app/state/index.js +7 -5
  92. package/src/runtime/app/state/public.d.ts +72 -0
  93. package/src/runtime/app/state/server.js +3 -0
  94. package/src/runtime/app/stores.js +15 -78
  95. package/src/runtime/client/bundle.js +1 -1
  96. package/src/runtime/client/client-entry.js +3 -0
  97. package/src/runtime/client/client.js +1336 -648
  98. package/src/runtime/client/constants.js +3 -6
  99. package/src/runtime/client/entry.js +24 -3
  100. package/src/runtime/client/fetcher.js +25 -25
  101. package/src/runtime/client/ndjson.js +1 -1
  102. package/src/runtime/client/parse.js +1 -1
  103. package/src/runtime/client/payload.js +17 -0
  104. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  105. package/src/runtime/client/remote-functions/command.svelte.js +37 -61
  106. package/src/runtime/client/remote-functions/form.svelte.js +267 -178
  107. package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
  108. package/src/runtime/client/remote-functions/query/index.js +10 -17
  109. package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
  110. package/src/runtime/client/remote-functions/query/proxy.js +5 -5
  111. package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
  112. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  113. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
  114. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
  115. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  116. package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
  117. package/src/runtime/client/snapshots.js +147 -0
  118. package/src/runtime/client/state.svelte.js +94 -55
  119. package/src/runtime/client/stream.js +3 -2
  120. package/src/runtime/client/types.d.ts +13 -9
  121. package/src/runtime/client/utils.js +22 -110
  122. package/src/runtime/components/root.svelte +56 -0
  123. package/src/runtime/env/dynamic/private.js +7 -0
  124. package/src/runtime/env/dynamic/public.js +7 -0
  125. package/src/runtime/env/static/private.js +6 -0
  126. package/src/runtime/env/static/public.js +6 -0
  127. package/src/runtime/form-utils.js +172 -61
  128. package/src/runtime/pathname.js +20 -32
  129. package/src/runtime/props.svelte.js +72 -0
  130. package/src/runtime/server/constants.js +0 -3
  131. package/src/runtime/server/cookie.js +72 -55
  132. package/src/runtime/server/csrf.js +65 -0
  133. package/src/runtime/server/data/index.js +49 -53
  134. package/src/runtime/server/dev.js +22 -0
  135. package/src/runtime/server/endpoint.js +6 -7
  136. package/src/runtime/server/env_module.js +0 -5
  137. package/src/runtime/server/errors.js +160 -0
  138. package/src/runtime/server/fetch.js +32 -39
  139. package/src/runtime/server/index.js +90 -64
  140. package/src/runtime/server/internal.js +71 -0
  141. package/src/runtime/server/page/actions.js +85 -64
  142. package/src/runtime/server/page/crypto.js +2 -2
  143. package/src/runtime/server/page/csp.js +88 -104
  144. package/src/runtime/server/page/data_serializer.js +24 -25
  145. package/src/runtime/server/page/index.js +36 -53
  146. package/src/runtime/server/page/load_data.js +50 -57
  147. package/src/runtime/server/page/render.js +173 -239
  148. package/src/runtime/server/page/respond_with_error.js +17 -31
  149. package/src/runtime/server/page/serialize_data.js +2 -13
  150. package/src/runtime/server/page/server_routing.js +85 -26
  151. package/src/runtime/server/remote-functions.js +640 -0
  152. package/src/runtime/server/respond.js +190 -131
  153. package/src/runtime/server/sourcemaps.js +183 -0
  154. package/src/runtime/server/state.js +53 -0
  155. package/src/runtime/server/utils.js +13 -155
  156. package/src/runtime/shared.js +20 -40
  157. package/src/runtime/utils.js +3 -0
  158. package/src/types/ambient-private.d.ts +11 -1
  159. package/src/types/ambient.d.ts +87 -36
  160. package/src/types/global-private.d.ts +25 -25
  161. package/src/types/internal.d.ts +163 -157
  162. package/src/types/private.d.ts +41 -1
  163. package/src/utils/error.js +28 -4
  164. package/src/utils/escape.js +9 -25
  165. package/src/utils/features.js +1 -1
  166. package/src/utils/filesystem.js +1 -23
  167. package/src/utils/fork.js +7 -2
  168. package/src/utils/hash.js +21 -0
  169. package/src/utils/http.js +8 -7
  170. package/src/utils/import.js +9 -2
  171. package/src/utils/imports.js +83 -0
  172. package/src/utils/mime.js +9 -0
  173. package/src/utils/page_nodes.js +6 -7
  174. package/src/utils/params.js +67 -0
  175. package/src/utils/regex.js +9 -0
  176. package/src/utils/routing.js +145 -73
  177. package/src/utils/shared-iterator.js +5 -0
  178. package/src/utils/streaming.js +14 -4
  179. package/src/utils/url.js +33 -2
  180. package/src/version.js +1 -1
  181. package/types/index.d.ts +2616 -2433
  182. package/types/index.d.ts.map +120 -106
  183. package/src/core/sync/write_ambient.js +0 -18
  184. package/src/core/sync/write_root.js +0 -148
  185. package/src/core/sync/write_tsconfig.js +0 -250
  186. package/src/exports/internal/server.js +0 -22
  187. package/src/exports/node/polyfills.js +0 -30
  188. package/src/runtime/server/app.js +0 -9
  189. package/src/runtime/server/remote.js +0 -457
  190. package/src/runtime/shared-server.js +0 -7
  191. package/src/runtime/telemetry/otel.js +0 -21
  192. package/src/runtime/telemetry/record_span.js +0 -65
  193. package/src/types/synthetic/$lib.md +0 -5
  194. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
  195. /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
@@ -1,10 +1,11 @@
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 { 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';
8
+ import { is_page_route } from '../create_manifest_data/index.js';
8
9
  const remove_relative_parent_traversals = (/** @type {string} */ path) =>
9
10
  path.replace(/\.\.\//g, '');
10
11
  const is_whitespace = (/** @type {string} */ char) => /\s/.test(char);
@@ -34,11 +35,11 @@ const is_whitespace = (/** @type {string} */ char) => /\s/.test(char);
34
35
  export function write_all_types(config, manifest_data, root) {
35
36
  if (!ts) return;
36
37
 
37
- const types_dir = `${config.kit.outDir}/types`;
38
+ const types_dir = `${config.outDir}/types`;
38
39
 
39
40
  // empty out files that no longer need to exist
40
41
  const routes_dir = remove_relative_parent_traversals(
41
- posixify(path.relative(root, config.kit.files.routes))
42
+ posixify(path.relative(root, config.files.routes))
42
43
  );
43
44
  const expected_directories = new Set(
44
45
  manifest_data.routes.map((route) => path.join(routes_dir, route.id))
@@ -48,7 +49,7 @@ export function write_all_types(config, manifest_data, root) {
48
49
  for (const file of walk(types_dir)) {
49
50
  const dir = path.dirname(file);
50
51
  if (!expected_directories.has(dir)) {
51
- rimraf(path.join(types_dir, file));
52
+ fs.rmSync(path.join(types_dir, file), { force: true, recursive: true });
52
53
  }
53
54
  }
54
55
  }
@@ -65,7 +66,7 @@ export function write_all_types(config, manifest_data, root) {
65
66
  for (const route of manifest_data.routes) {
66
67
  if (!route.leaf && !route.layout && !route.endpoint) continue; // nothing to do
67
68
 
68
- const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id);
69
+ const outdir = path.join(config.outDir, 'types', routes_dir, route.id);
69
70
 
70
71
  // check if the types are out of date
71
72
  /** @type {string[]} */
@@ -147,7 +148,7 @@ export function write_types(config, manifest_data, file, root) {
147
148
  return;
148
149
  }
149
150
 
150
- const id = '/' + posixify(path.relative(config.kit.files.routes, path.dirname(file)));
151
+ const id = '/' + posixify(path.relative(config.files.routes, path.dirname(file)));
151
152
 
152
153
  const route = manifest_data.routes.find((route) => route.id === id);
153
154
  if (!route) return;
@@ -181,12 +182,15 @@ function create_routes_map(manifest_data) {
181
182
  */
182
183
  function update_types(config, routes, route, root, to_delete = new Set()) {
183
184
  const routes_dir = remove_relative_parent_traversals(
184
- posixify(path.relative(root, config.kit.files.routes))
185
+ posixify(path.relative(root, config.files.routes))
185
186
  );
186
- const outdir = path.join(config.kit.outDir, 'types', routes_dir, route.id);
187
+ const outdir = path.join(config.outDir, 'types', routes_dir, route.id);
187
188
 
188
189
  // now generate new types
189
- const imports = ["import type * as Kit from '@sveltejs/kit';"];
190
+ const imports = [
191
+ "import type * as Kit from '@sveltejs/kit';",
192
+ "import { MatcherParam } from '@sveltejs/kit/params';"
193
+ ];
190
194
 
191
195
  /** @type {string[]} */
192
196
  const declarations = [];
@@ -198,11 +202,6 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
198
202
  // Makes sure a type is "repackaged" and therefore more readable
199
203
  declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
200
204
 
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
205
  declarations.push(
207
206
  'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';'
208
207
  );
@@ -236,7 +235,10 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
236
235
  'type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;',
237
236
 
238
237
  // Re-export `Snapshot` from @sveltejs/kit — in future we could use this to infer <T> from the return type of `snapshot.capture`
239
- 'export type Snapshot<T = any> = Kit.Snapshot<T>;'
238
+ '/** @deprecated Use the `snapshot` helper from `$app/navigation` instead. */',
239
+ 'export type Snapshot<T = any> = Kit.Snapshot<T>;',
240
+
241
+ 'export type ErrorProps = { error: App.Error };'
240
242
  );
241
243
  }
242
244
 
@@ -268,15 +270,8 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
268
270
 
269
271
  if (route.leaf.server) {
270
272
  exports.push(
271
- 'export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>'
272
- );
273
- exports.push(
274
- 'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>'
275
- );
276
- }
277
-
278
- if (route.leaf.server) {
279
- exports.push(
273
+ 'export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>',
274
+ 'export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>',
280
275
  'export type PageProps = { params: RouteParams; data: PageData; form: ActionData }'
281
276
  );
282
277
  } else {
@@ -288,7 +283,9 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
288
283
  let all_pages_have_load = true;
289
284
  /** @type {import('types').RouteParam[]} */
290
285
  const layout_params = [];
291
- const ids = ['RouteId'];
286
+ // a layout can live in a directory that has no `+page` of its own, in which case its own id
287
+ // is never the matched route — a request to a colocated `+server` doesn't execute layouts
288
+ const ids = is_page_route(route) ? ['RouteId'] : [];
292
289
 
293
290
  route.layout.child_pages?.forEach((page) => {
294
291
  const leaf = routes.get(page);
@@ -322,7 +319,7 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
322
319
  ids.push('null');
323
320
  }
324
321
 
325
- declarations.push(`type LayoutRouteId = ${ids.join(' | ')}`);
322
+ declarations.push(`type LayoutRouteId = ${ids.join(' | ') || 'never'}`);
326
323
 
327
324
  declarations.push(
328
325
  'type LayoutParams = RouteParams & ' + generate_params_type(layout_params, outdir, config)
@@ -357,7 +354,9 @@ function update_types(config, routes, route, root, to_delete = new Set()) {
357
354
  }
358
355
 
359
356
  if (route.leaf?.server || route.layout?.server || route.endpoint) {
360
- exports.push('export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;');
357
+ exports.push(
358
+ "export type RequestEvent = import('$app/server').RequestEvent<RouteParams, RouteId>;"
359
+ );
361
360
  }
362
361
 
363
362
  const output = [imports.join('\n'), declarations.join('\n'), exports.join('\n')]
@@ -437,7 +436,7 @@ function process_node(node, outdir, is_page, proxies, root, all_pages_have_load
437
436
  'type ExtractActionFailure<T> = T extends Kit.ActionFailure<infer X> ? X extends void ? never : X : never;',
438
437
  'type ActionsFailure<T extends Record<string, (...args: any) => any>> = { [Key in keyof T]: Exclude<ExtractActionFailure<Awaited<ReturnType<T[Key]>>>, void>; }[keyof T];',
439
438
  `type ActionsExport = typeof import('${from}').actions`,
440
- 'export type SubmitFunction = Kit.SubmitFunction<Expand<ActionsSuccess<ActionsExport>>, Expand<ActionsFailure<ActionsExport>>>'
439
+ "export type SubmitFunction = import('$app/forms').SubmitFunction<Expand<ActionsSuccess<ActionsExport>>, Expand<ActionsFailure<ActionsExport>>>"
441
440
  );
442
441
 
443
442
  type = 'Expand<Kit.AwaitedActions<ActionsExport>> | null';
@@ -604,16 +603,21 @@ function replace_ext_with_js(file_path) {
604
603
  * @param {import('types').ValidatedConfig} config
605
604
  */
606
605
  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')));
606
+ const path_to_params = () => {
607
+ const params_file =
608
+ resolve_entry(config.files.params) ?? config.files.params.replace(/\.(js|ts)$/, '') + '.js';
609
+
610
+ return posixify(path.relative(outdir, params_file));
611
+ };
612
+
613
+ const params_import = path_to_params();
610
614
 
611
615
  return `{ ${params
612
616
  .map(
613
617
  (param) =>
614
- `${param.name}${param.optional ? '?' : ''}: ${
618
+ `${/^\w+$/.test(param.name) ? param.name : `'${param.name}'`}${param.optional ? '?' : ''}: ${
615
619
  param.matcher
616
- ? `MatcherParam<typeof import('${path_to_matcher(param.matcher)}').match>`
620
+ ? `MatcherParam<(typeof import('${params_import}').params)[${JSON.stringify(param.matcher)}]>`
617
621
  : 'string'
618
622
  }${param.optional ? ' | undefined' : ''}`
619
623
  )
@@ -642,6 +646,16 @@ export function tweak_types(content, is_server) {
642
646
  const code = new MagicString(content);
643
647
 
644
648
  const exports = new Map();
649
+ /** @param {import('typescript').BindingName} name */
650
+ function add_export(name) {
651
+ if (ts.isIdentifier(name)) {
652
+ if (names.has(name.text)) exports.set(name.text, name.text);
653
+ } else {
654
+ for (const element of name.elements) {
655
+ if (ts.isBindingElement(element)) add_export(element.name);
656
+ }
657
+ }
658
+ }
645
659
 
646
660
  ast.forEachChild((node) => {
647
661
  if (
@@ -668,9 +682,7 @@ export function tweak_types(content, is_server) {
668
682
 
669
683
  if (ts.isVariableStatement(node)) {
670
684
  node.declarationList.declarations.forEach((declaration) => {
671
- if (ts.isIdentifier(declaration.name) && names.has(declaration.name.text)) {
672
- exports.set(declaration.name.text, declaration.name.text);
673
- }
685
+ add_export(declaration.name);
674
686
  });
675
687
  }
676
688
  }
@@ -713,6 +725,62 @@ export function tweak_types(content, is_server) {
713
725
  return _modified;
714
726
  }
715
727
 
728
+ /**
729
+ * @param {number} name_end position of the identifier the annotation is attached to
730
+ * @param {import('typescript').TypeNode} type_node
731
+ * @returns {string} the removed annotation's text
732
+ */
733
+ function strip_type_annotation(name_end, type_node) {
734
+ let a = type_node.pos;
735
+ const b = type_node.end;
736
+ while (is_whitespace(content[a])) a += 1;
737
+
738
+ const type = content.slice(a, b);
739
+ code.remove(name_end, type_node.end);
740
+ modified = true;
741
+ return type;
742
+ }
743
+
744
+ /**
745
+ * Types the first parameter of an untyped arrow/function expression.
746
+ * @param {import('typescript').Expression | undefined} rhs
747
+ * @param {string} type
748
+ * @returns {boolean} `false` if there was nothing to annotate
749
+ */
750
+ function annotate_first_param(rhs, type) {
751
+ if (
752
+ !rhs ||
753
+ !(ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) ||
754
+ !rhs.parameters.length
755
+ ) {
756
+ return false;
757
+ }
758
+
759
+ const arg = rhs.parameters[0];
760
+ const add_parens = content[arg.pos - 1] !== '(';
761
+
762
+ if (add_parens) code.prependRight(arg.pos, '(');
763
+
764
+ if (arg.type) return false;
765
+
766
+ code.appendLeft(arg.name.end, `: ${type}` + (add_parens ? ')' : ''));
767
+ return true;
768
+ }
769
+
770
+ /**
771
+ * @param {import('typescript').Expression | undefined} initializer
772
+ * @param {(prop: import('typescript').PropertyAssignment) => void} callback
773
+ */
774
+ function for_each_action(initializer, callback) {
775
+ if (initializer && ts.isObjectLiteralExpression(initializer)) {
776
+ for (const prop of initializer.properties) {
777
+ if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
778
+ callback(prop);
779
+ }
780
+ }
781
+ }
782
+ }
783
+
716
784
  ast.forEachChild((node) => {
717
785
  if (ts.isFunctionDeclaration(node) && node.name?.text && node.name?.text === 'load') {
718
786
  // remove JSDoc comment above `export function load ...`
@@ -738,42 +806,13 @@ export function tweak_types(content, is_server) {
738
806
  // edge case — remove JSDoc comment above individual export
739
807
  replace_jsdoc_type_tags(declaration, declaration.initializer);
740
808
 
741
- // remove type from `export const load: Load ...`
742
809
  if (declaration.type) {
743
- let a = declaration.type.pos;
744
- const b = declaration.type.end;
745
- while (is_whitespace(content[a])) a += 1;
810
+ const type = strip_type_annotation(declaration.name.end, declaration.type);
746
811
 
747
- const type = content.slice(a, b);
748
- code.remove(declaration.name.end, declaration.type.end);
749
-
750
- const rhs = declaration.initializer;
751
-
752
- if (
753
- rhs &&
754
- (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
755
- rhs.parameters.length
756
- ) {
757
- const arg = rhs.parameters[0];
758
- const add_parens = content[arg.pos - 1] !== '(';
759
-
760
- if (add_parens) code.prependRight(arg.pos, '(');
761
-
762
- if (arg && !arg.type) {
763
- code.appendLeft(
764
- arg.name.end,
765
- `: Parameters<${type}>[0]` + (add_parens ? ')' : '')
766
- );
767
- } else {
768
- // prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs
769
- code.append(`;null as any as ${type};`);
770
- }
771
- } else {
812
+ if (!annotate_first_param(declaration.initializer, `Parameters<${type}>[0]`)) {
772
813
  // prevent "type X is imported but not used" (isn't silenced by @ts-nocheck) when svelte-check runs
773
814
  code.append(`;null as any as ${type};`);
774
815
  }
775
-
776
- modified = true;
777
816
  }
778
817
  } else if (
779
818
  is_server &&
@@ -785,69 +824,34 @@ export function tweak_types(content, is_server) {
785
824
  const removed = replace_jsdoc_type_tags(node, declaration.initializer);
786
825
  // ... and move type to each individual action
787
826
  if (removed) {
788
- const rhs = declaration.initializer;
789
- if (ts.isObjectLiteralExpression(rhs)) {
790
- for (const prop of rhs.properties) {
791
- if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
792
- const rhs = prop.initializer;
793
- const replaced = replace_jsdoc_type_tags(prop, rhs);
794
- if (
795
- !replaced &&
796
- rhs &&
797
- (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
798
- rhs.parameters?.[0]
799
- ) {
800
- const name = ts.isIdentifier(rhs.parameters[0].name)
801
- ? rhs.parameters[0].name.text
802
- : 'event';
803
- code.prependRight(
804
- rhs.pos,
805
- `/** @param {import('./$types').RequestEvent} ${name} */ `
806
- );
807
- }
808
- }
827
+ for_each_action(declaration.initializer, (prop) => {
828
+ const rhs = prop.initializer;
829
+ const replaced = replace_jsdoc_type_tags(prop, rhs);
830
+ if (
831
+ !replaced &&
832
+ rhs &&
833
+ (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
834
+ rhs.parameters?.[0]
835
+ ) {
836
+ const name = ts.isIdentifier(rhs.parameters[0].name)
837
+ ? rhs.parameters[0].name.text
838
+ : 'event';
839
+ code.prependRight(
840
+ rhs.pos,
841
+ `/** @param {import('./$types').RequestEvent} ${name} */ `
842
+ );
809
843
  }
810
- }
844
+ });
811
845
  }
812
846
 
813
- // remove type from `export const actions: Actions ...`
814
847
  if (declaration.type) {
815
- let a = declaration.type.pos;
816
- const b = declaration.type.end;
817
- while (is_whitespace(content[a])) a += 1;
818
-
819
- const type = content.slice(a, b);
820
- code.remove(declaration.name.end, declaration.type.end);
848
+ const type = strip_type_annotation(declaration.name.end, declaration.type);
821
849
  code.append(`;null as any as ${type};`);
822
- modified = true;
823
850
 
824
851
  // ... and move type to each individual action
825
- const rhs = declaration.initializer;
826
- if (ts.isObjectLiteralExpression(rhs)) {
827
- for (const prop of rhs.properties) {
828
- if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
829
- const rhs = prop.initializer;
830
-
831
- if (
832
- rhs &&
833
- (ts.isArrowFunction(rhs) || ts.isFunctionExpression(rhs)) &&
834
- rhs.parameters.length
835
- ) {
836
- const arg = rhs.parameters[0];
837
- const add_parens = content[arg.pos - 1] !== '(';
838
-
839
- if (add_parens) code.prependRight(arg.pos, '(');
840
-
841
- if (arg && !arg.type) {
842
- code.appendLeft(
843
- arg.name.end,
844
- ": import('./$types').RequestEvent" + (add_parens ? ')' : '')
845
- );
846
- }
847
- }
848
- }
849
- }
850
- }
852
+ for_each_action(declaration.initializer, (prop) => {
853
+ annotate_first_param(prop.initializer, "import('./$types').RequestEvent");
854
+ });
851
855
  }
852
856
  }
853
857
  }
package/src/core/utils.js CHANGED
@@ -7,7 +7,7 @@ import { noop } from '../utils/functions.js';
7
7
  import { posixify } from '../utils/os.js';
8
8
 
9
9
  /**
10
- * Resolved path of the `runtime` directory
10
+ * Resolved path of the `runtime` directory posix-ified
11
11
  *
12
12
  * TODO Windows issue:
13
13
  * Vite or sth else somehow sets the driver letter inconsistently to lower or upper case depending on the run environment.
@@ -25,23 +25,48 @@ export const runtime_directory = posixify(fileURLToPath(new URL('../runtime', im
25
25
  */
26
26
  export function get_runtime_base(root) {
27
27
  return runtime_directory.startsWith(root)
28
- ? `/${path.relative(root, runtime_directory)}`
28
+ ? `/${posixify(path.relative(root, runtime_directory))}`
29
29
  : to_fs(runtime_directory);
30
30
  }
31
31
 
32
32
  /** @param {{ verbose: boolean }} opts */
33
- export function logger({ verbose }) {
33
+ export function logger({ verbose } = { verbose: true }) {
34
34
  /** @type {import('types').Logger} */
35
- const log = (msg) => console.log(msg.replace(/^/gm, ' '));
35
+ const log = (msg) => console.log(msg);
36
36
 
37
37
  /** @param {string} msg */
38
- const err = (msg) => console.error(msg.replace(/^/gm, ' '));
38
+ const err = (msg) => console.error(msg);
39
39
 
40
40
  log.success = (msg) => log(styleText('green', `✔ ${msg}`));
41
41
  log.error = (msg) => err(styleText(['bold', 'red'], msg));
42
42
  log.warn = (msg) => log(styleText(['bold', 'yellow'], msg));
43
43
  log.minor = verbose ? (msg) => log(styleText('grey', msg)) : noop;
44
44
  log.info = verbose ? log : noop;
45
+ log.err = err;
46
+
47
+ log.prettyError = (error, caller) => {
48
+ /** @type {unknown} */
49
+ let e = error;
50
+
51
+ while (e instanceof Error) {
52
+ let stack = e.stack;
53
+ if (stack) {
54
+ if (caller) {
55
+ const i = stack.indexOf(caller);
56
+ // Cut the stack trace off at the point when our internal one starts
57
+ stack = stack.slice(0, stack.lastIndexOf('\n', i));
58
+ }
59
+
60
+ err(stack);
61
+ }
62
+
63
+ e = e.cause;
64
+ }
65
+
66
+ if (e) {
67
+ err(String(e));
68
+ }
69
+ };
45
70
 
46
71
  return log;
47
72
  }
@@ -0,0 +1,77 @@
1
+ /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
+ /** @import { DefinedEnvVars, EnvVarConfig } from '@sveltejs/kit/env' */
3
+
4
+ /**
5
+ * Utility for defining [environment variables](https://svelte.dev/docs/kit/environment-variables),
6
+ * which are made available via `$app/env/public` and `$app/env/private`.
7
+ *
8
+ * @example
9
+ * ```js
10
+ * import { defineEnvVars } from '@sveltejs/kit/env';
11
+ * import * as v from 'valibot';
12
+ *
13
+ * export const variables = defineEnvVars({
14
+ * API_URL: {
15
+ * schema: v.pipe(v.string(), v.url())
16
+ * },
17
+ * PORT: {
18
+ * schema: (value) => {
19
+ * if (value === undefined) return 3000;
20
+ * const port = Number(value);
21
+ * if (!Number.isInteger(port)) throw new Error('PORT must be an integer');
22
+ * return port;
23
+ * }
24
+ * }
25
+ * });
26
+ * ```
27
+ *
28
+ * @template {Record<string, EnvVarConfig<any>>} T
29
+ * @param {T} variables
30
+ * @returns {DefinedEnvVars<T>}
31
+ */
32
+ export function defineEnvVars(variables) {
33
+ /** @type {Record<string, EnvVarConfig<any>>} */
34
+ const normalized = {};
35
+
36
+ for (const [name, config] of Object.entries(variables)) {
37
+ // standard schemas can be callable (e.g. ArkType), so a function is only a validator if it isn't one
38
+ normalized[name] =
39
+ typeof config.schema === 'function' && !('~standard' in config.schema)
40
+ ? { ...config, schema: normalize_env_schema(config.schema) }
41
+ : config;
42
+ }
43
+
44
+ return /** @type {DefinedEnvVars<T>} */ (normalized);
45
+ }
46
+
47
+ /**
48
+ * @param {(value: string | undefined) => any} fn
49
+ * @returns {StandardSchemaV1<string | undefined, any>}
50
+ */
51
+ function normalize_env_schema(fn) {
52
+ return /** @type {StandardSchemaV1<string | undefined, any>} */ (
53
+ /** @type {unknown} */ ({
54
+ '~standard': {
55
+ validate(/** @type {unknown} */ value) {
56
+ let result;
57
+
58
+ try {
59
+ result = fn(/** @type {string | undefined} */ (value));
60
+ } catch (error) {
61
+ return {
62
+ issues: [
63
+ {
64
+ message: error instanceof Error ? error.message || 'Invalid value' : String(error)
65
+ }
66
+ ]
67
+ };
68
+ }
69
+
70
+ if (result instanceof Promise) return result; // will be rejected upstream
71
+
72
+ return { value: result };
73
+ }
74
+ }
75
+ })
76
+ );
77
+ }
@@ -0,0 +1,55 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+
3
+ export * from './index.js';
4
+
5
+ /**
6
+ * [Environment variables](https://svelte.dev/docs/kit/environment-variables) can be configured by exporting
7
+ * a `variables` object from `src/env.ts`, using [`defineEnvVars`](https://svelte.dev/docs/kit/@sveltejs-kit-env#defineEnvVars).
8
+ */
9
+ export interface EnvVarConfig<T> {
10
+ /**
11
+ * Whether the environment variable can be accessed by client-side code.
12
+ * - if `true`, it can be imported from `$app/env/public`
13
+ * - if `false`, it can be imported from `$app/env/private`, which is a [server-only module](https://svelte.dev/docs/kit/server-only-modules)
14
+ * @default false
15
+ */
16
+ public?: boolean;
17
+ /**
18
+ * Whether the value is determined at build time or when the app runs.
19
+ * - if `true`, the build time value is inlined into the bundle. This enables optimisations like dead-code elimination
20
+ * - if `false`, the value is read from the environment when the app starts
21
+ * @default false
22
+ */
23
+ static?: boolean;
24
+ /**
25
+ * A [Standard Schema](https://standardschema.dev/) validator that is applied to the value when the app starts.
26
+ * Alternatively, a function that returns the (possibly transformed) value, or throws an error explaining
27
+ * the problem. Returning `undefined` is valid, so a function can describe an optional variable.
28
+ * The validator can output any value — not necessarily a string — but public, non-static values must be
29
+ * serializable by [devalue](https://github.com/sveltejs/devalue) so that they can be sent to the browser.
30
+ *
31
+ * If omitted, the value must be set, but may be an empty string.
32
+ */
33
+ schema?: StandardSchemaV1<string | undefined, T> | ((value: string | undefined) => T | undefined);
34
+ /**
35
+ * A description of the variable that will be used for inline documentation on hover.
36
+ */
37
+ description?: string;
38
+ }
39
+
40
+ /**
41
+ * The return type of [`defineEnvVars`](https://svelte.dev/docs/kit/@sveltejs-kit-env#defineEnvVars).
42
+ */
43
+ export type DefinedEnvVars<T extends Record<string, EnvVarConfig<any>>> = {
44
+ readonly [K in keyof T]: EnvVarEntry<T[K]>;
45
+ };
46
+
47
+ /**
48
+ * Normalizes an environment variable config's schema (standard schema or function) to standard schema.
49
+ */
50
+ type EnvVarEntry<C extends EnvVarConfig<any>> =
51
+ C['schema'] extends StandardSchemaV1<any, any>
52
+ ? C
53
+ : C['schema'] extends (value: any) => infer R
54
+ ? Omit<C, 'schema'> & { schema: StandardSchemaV1<string | undefined, R> }
55
+ : C;
@@ -1,14 +1,8 @@
1
- /** @import { EnvVarConfig } from '@sveltejs/kit' */
2
-
3
1
  export { sequence } from './sequence.js';
4
2
 
5
3
  /**
6
- * Utility for defining [environment variables](https://svelte.dev/docs/kit/environment-variables),
7
- * which are made available via `$app/env/public` and `$app/env/private`.
8
- * @template {Record<string, EnvVarConfig<any>>} T
9
- * @param {T} variables
10
- * @returns {T}
4
+ * @internal
11
5
  */
12
- export function defineEnvVars(variables) {
13
- return variables;
6
+ export function defineEnvVars() {
7
+ throw new Error(`\`defineEnvVars\` has moved — import it from \`@sveltejs/kit/env\` instead`);
14
8
  }