@sveltejs/kit 1.0.0-next.296 → 1.0.0-next.297

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.
@@ -795,7 +795,7 @@ function create_client({ target, session, base, trailing_slash }) {
795
795
  * @param {import('./types').NavigationIntent} intent
796
796
  * @param {boolean} no_cache
797
797
  */
798
- async function load_route(route, { id, url, path }, no_cache) {
798
+ async function load_route(route, { id, url, path, routes }, no_cache) {
799
799
  if (!no_cache) {
800
800
  const cached = cache.get(id);
801
801
  if (cached) return cached;
@@ -804,7 +804,7 @@ function create_client({ target, session, base, trailing_slash }) {
804
804
  const [pattern, a, b, get_params, shadow_key] = route;
805
805
  const params = get_params
806
806
  ? // the pattern is for the route which we've already matched to this path
807
- get_params(/** @type {RegExpExecArray} */ (pattern.exec(path)))
807
+ get_params(/** @type {RegExpExecArray} */ (pattern.exec(path)))
808
808
  : {};
809
809
 
810
810
  const changed = current.url && {
@@ -876,10 +876,14 @@ function create_client({ target, session, base, trailing_slash }) {
876
876
  }
877
877
 
878
878
  if (res.status === 204) {
879
- // fallthrough
880
- return;
879
+ if (route !== routes[routes.length - 1]) {
880
+ // fallthrough
881
+ return;
882
+ }
883
+ props = {};
884
+ } else {
885
+ props = await res.json();
881
886
  }
882
- props = await res.json();
883
887
  } else {
884
888
  status = res.status;
885
889
  error = new Error('Failed to load data');
@@ -1720,7 +1720,9 @@ async function load_node({
1720
1720
 
1721
1721
  response = await respond(new Request(new URL(requested, event.url).href, opts), options, {
1722
1722
  fetched: requested,
1723
- initiator: route
1723
+ getClientAddress: state.getClientAddress,
1724
+ initiator: route,
1725
+ prerender: state.prerender
1724
1726
  });
1725
1727
 
1726
1728
  if (state.prerender) {
@@ -2503,7 +2505,7 @@ const DATA_SUFFIX = '/__data.json';
2503
2505
  const default_transform = ({ html }) => html;
2504
2506
 
2505
2507
  /** @type {import('types').Respond} */
2506
- async function respond(request, options, state = {}) {
2508
+ async function respond(request, options, state) {
2507
2509
  const url = new URL(request.url);
2508
2510
 
2509
2511
  const normalized = normalize_path(url.pathname, options.trailing_slash);
@@ -2544,11 +2546,26 @@ async function respond(request, options, state = {}) {
2544
2546
 
2545
2547
  /** @type {import('types').RequestEvent} */
2546
2548
  const event = {
2547
- request,
2548
- url,
2549
- params: {},
2549
+ get clientAddress() {
2550
+ if (!state.getClientAddress) {
2551
+ throw new Error(
2552
+ `${
2553
+ import.meta.env.VITE_SVELTEKIT_ADAPTER_NAME
2554
+ } does not specify getClientAddress. Please raise an issue`
2555
+ );
2556
+ }
2557
+
2558
+ Object.defineProperty(event, 'clientAddress', {
2559
+ value: state.getClientAddress()
2560
+ });
2561
+
2562
+ return event.clientAddress;
2563
+ },
2550
2564
  locals: {},
2551
- platform: state.platform
2565
+ params: {},
2566
+ platform: state.platform,
2567
+ request,
2568
+ url
2552
2569
  };
2553
2570
 
2554
2571
  // TODO remove this for 1.0
@@ -2750,6 +2767,10 @@ async function respond(request, options, state = {}) {
2750
2767
  });
2751
2768
  }
2752
2769
 
2770
+ if (state.prerender) {
2771
+ return new Response('not found', { status: 404 });
2772
+ }
2773
+
2753
2774
  // we can't load the endpoint from our own manifest,
2754
2775
  // so we need to make an actual HTTP request
2755
2776
  return await fetch(request);
@@ -271,62 +271,72 @@ async function create_plugin(config, cwd) {
271
271
 
272
272
  const template = load_template(cwd, config);
273
273
 
274
- const rendered = await respond(request, {
275
- amp: config.kit.amp,
276
- csp: config.kit.csp,
277
- dev: true,
278
- floc: config.kit.floc,
279
- get_stack: (error) => {
280
- return fix_stack_trace(error);
281
- },
282
- handle_error: (error, event) => {
283
- hooks.handleError({
284
- error: new Proxy(error, {
285
- get: (target, property) => {
286
- if (property === 'stack') {
287
- return fix_stack_trace(error);
274
+ const rendered = await respond(
275
+ request,
276
+ {
277
+ amp: config.kit.amp,
278
+ csp: config.kit.csp,
279
+ dev: true,
280
+ floc: config.kit.floc,
281
+ get_stack: (error) => {
282
+ return fix_stack_trace(error);
283
+ },
284
+ handle_error: (error, event) => {
285
+ hooks.handleError({
286
+ error: new Proxy(error, {
287
+ get: (target, property) => {
288
+ if (property === 'stack') {
289
+ return fix_stack_trace(error);
290
+ }
291
+
292
+ return Reflect.get(target, property, target);
288
293
  }
289
-
290
- return Reflect.get(target, property, target);
294
+ }),
295
+ event,
296
+
297
+ // TODO remove for 1.0
298
+ // @ts-expect-error
299
+ get request() {
300
+ throw new Error(
301
+ 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
302
+ );
291
303
  }
292
- }),
293
- event,
294
-
295
- // TODO remove for 1.0
296
- // @ts-expect-error
297
- get request() {
298
- throw new Error(
299
- 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
300
- );
301
- }
302
- });
303
- },
304
- hooks,
305
- hydrate: config.kit.browser.hydrate,
306
- manifest,
307
- method_override: config.kit.methodOverride,
308
- paths: {
309
- base: config.kit.paths.base,
310
- assets
311
- },
312
- prefix: '',
313
- prerender: config.kit.prerender.enabled,
314
- read: (file) => fs__default.readFileSync(path__default.join(config.kit.files.assets, file)),
315
- root,
316
- router: config.kit.browser.router,
317
- template: ({ head, body, assets, nonce }) => {
318
- return (
319
- template
320
- .replace(/%svelte\.assets%/g, assets)
321
- .replace(/%svelte\.nonce%/g, nonce)
322
- // head and body must be replaced last, in case someone tries to sneak in %svelte.assets% etc
323
- .replace('%svelte.head%', () => head)
324
- .replace('%svelte.body%', () => body)
325
- );
304
+ });
305
+ },
306
+ hooks,
307
+ hydrate: config.kit.browser.hydrate,
308
+ manifest,
309
+ method_override: config.kit.methodOverride,
310
+ paths: {
311
+ base: config.kit.paths.base,
312
+ assets
313
+ },
314
+ prefix: '',
315
+ prerender: config.kit.prerender.enabled,
316
+ read: (file) => fs__default.readFileSync(path__default.join(config.kit.files.assets, file)),
317
+ root,
318
+ router: config.kit.browser.router,
319
+ template: ({ head, body, assets, nonce }) => {
320
+ return (
321
+ template
322
+ .replace(/%svelte\.assets%/g, assets)
323
+ .replace(/%svelte\.nonce%/g, nonce)
324
+ // head and body must be replaced last, in case someone tries to sneak in %svelte.assets% etc
325
+ .replace('%svelte.head%', () => head)
326
+ .replace('%svelte.body%', () => body)
327
+ );
328
+ },
329
+ template_contains_nonce: template.includes('%svelte.nonce%'),
330
+ trailing_slash: config.kit.trailingSlash
326
331
  },
327
- template_contains_nonce: template.includes('%svelte.nonce%'),
328
- trailing_slash: config.kit.trailingSlash
329
- });
332
+ {
333
+ getClientAddress: () => {
334
+ const { remoteAddress } = req.socket;
335
+ if (remoteAddress) return remoteAddress;
336
+ throw new Error('Could not determine clientAddress');
337
+ }
338
+ }
339
+ );
330
340
 
331
341
  if (rendered) {
332
342
  setResponse(res, rendered);
@@ -500,6 +500,8 @@ async function build_server(
500
500
 
501
501
  print_config_conflicts(conflicts, 'kit.vite.', 'build_server');
502
502
 
503
+ process.env.VITE_SVELTEKIT_ADAPTER_NAME = config.kit.adapter?.name;
504
+
503
505
  const { chunks } = await create_build(merged_config);
504
506
 
505
507
  /** @type {import('vite').Manifest} */
@@ -1073,6 +1075,7 @@ async function prerender({ config, entries, files, log }) {
1073
1075
  const dependencies = new Map();
1074
1076
 
1075
1077
  const response = await server.respond(new Request(`http://sveltekit-prerender${encoded}`), {
1078
+ getClientAddress,
1076
1079
  prerender: {
1077
1080
  default: config.kit.prerender.default,
1078
1081
  dependencies
@@ -1209,6 +1212,7 @@ async function prerender({ config, entries, files, log }) {
1209
1212
  }
1210
1213
 
1211
1214
  const rendered = await server.respond(new Request('http://sveltekit-prerender/[fallback]'), {
1215
+ getClientAddress,
1212
1216
  prerender: {
1213
1217
  fallback: true,
1214
1218
  default: false,
@@ -1223,6 +1227,11 @@ async function prerender({ config, entries, files, log }) {
1223
1227
  return prerendered;
1224
1228
  }
1225
1229
 
1230
+ /** @return {string} */
1231
+ function getClientAddress() {
1232
+ throw new Error('Cannot read clientAddress during prerendering');
1233
+ }
1234
+
1226
1235
  /**
1227
1236
  * @param {import('types').ValidatedConfig} config
1228
1237
  * @param {{ log: import('types').Logger }} opts
@@ -145,7 +145,16 @@ async function preview({ port, host, config, https: use_https = false }) {
145
145
  return res.end(err.reason || 'Invalid request body');
146
146
  }
147
147
 
148
- setResponse(res, await server.respond(request));
148
+ setResponse(
149
+ res,
150
+ await server.respond(request, {
151
+ getClientAddress: () => {
152
+ const { remoteAddress } = req.socket;
153
+ if (remoteAddress) return remoteAddress;
154
+ throw new Error('Could not determine clientAddress');
155
+ }
156
+ })
157
+ );
149
158
  }
150
159
  ]);
151
160
 
@@ -895,6 +895,22 @@ function validate(config, out, user_file) {
895
895
  }
896
896
  }
897
897
 
898
+ /** @param {string} imports */
899
+ const header = (imports) => `
900
+ // this file is auto-generated
901
+ import type { ${imports} } from '@sveltejs/kit';`;
902
+
903
+ /** @param {string} arg */
904
+ const endpoint = (arg) => `
905
+ export type RequestHandler<Output extends ResponseBody = ResponseBody> = GenericRequestHandler<${arg}, Output>;`;
906
+
907
+ /** @param {string} arg */
908
+ const page = (arg) => `
909
+ export type Load<
910
+ InputProps extends Record<string, any> = Record<string, any>,
911
+ OutputProps extends Record<string, any> = InputProps
912
+ > = GenericLoad<${arg}, InputProps, OutputProps>;`;
913
+
898
914
  /**
899
915
  * @param {import('types').ValidatedConfig} config
900
916
  * @param {import('types').ManifestData} manifest_data
@@ -948,25 +964,25 @@ function write_types(config, manifest_data) {
948
964
  const arg =
949
965
  params.length > 0 ? `{ ${params.map((param) => `${param}: string`).join('; ')} }` : '{}';
950
966
 
951
- const imports = [
952
- type !== 'page' && 'RequestHandler as GenericRequestHandler',
953
- type !== 'endpoint' && 'Load as GenericLoad'
954
- ]
955
- .filter(Boolean)
956
- .join(', ');
957
-
958
- const file = `${config.kit.outDir}/types/${key || 'index'}.d.ts`;
959
- const content = [
960
- '// this file is auto-generated',
961
- `import type { ${imports} } from '@sveltejs/kit';`,
962
- type !== 'page' && `export type RequestHandler = GenericRequestHandler<${arg}>;`,
963
- type !== 'endpoint' &&
964
- `export type Load<Props = Record<string, any>> = GenericLoad<${arg}, Props>;`
965
- ]
966
- .filter(Boolean)
967
- .join('\n');
967
+ const imports = [];
968
+ const content = [];
969
+
970
+ if (type !== 'page') {
971
+ imports.push('RequestHandler as GenericRequestHandler, ResponseBody');
972
+ content.push(endpoint(arg));
973
+ }
968
974
 
969
- write_if_changed(file, content);
975
+ if (type !== 'endpoint') {
976
+ imports.push('Load as GenericLoad');
977
+ content.push(page(arg));
978
+ }
979
+
980
+ content.unshift(header(imports.join(', ')));
981
+
982
+ write_if_changed(
983
+ `${config.kit.outDir}/types/${key || 'index'}.d.ts`,
984
+ content.join('\n').trim()
985
+ );
970
986
  });
971
987
  }
972
988
 
package/dist/cli.js CHANGED
@@ -870,7 +870,7 @@ async function launch(port, https) {
870
870
  exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
871
871
  }
872
872
 
873
- const prog = sade('svelte-kit').version('1.0.0-next.296');
873
+ const prog = sade('svelte-kit').version('1.0.0-next.297');
874
874
 
875
875
  prog
876
876
  .command('dev')
@@ -1043,7 +1043,7 @@ async function check_port(port) {
1043
1043
  function welcome({ port, host, https, open, loose, allow, cwd }) {
1044
1044
  if (open) launch(port, https);
1045
1045
 
1046
- console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.296'}\n`));
1046
+ console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.297'}\n`));
1047
1047
 
1048
1048
  const protocol = https ? 'https:' : 'http:';
1049
1049
  const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.296",
3
+ "version": "1.0.0-next.297",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
package/types/index.d.ts CHANGED
@@ -6,11 +6,11 @@ import './ambient';
6
6
  import { CompileOptions } from 'svelte/types/compiler/interfaces';
7
7
  import {
8
8
  AdapterEntry,
9
- Body,
10
9
  CspDirectives,
11
10
  Either,
12
11
  ErrorLoadInput,
13
12
  Fallthrough,
13
+ JSONValue,
14
14
  LoadInput,
15
15
  LoadOutput,
16
16
  Logger,
@@ -158,7 +158,10 @@ export interface Config {
158
158
  preprocess?: any;
159
159
  }
160
160
 
161
- export interface ErrorLoad<Params = Record<string, string>, Props = Record<string, any>> {
161
+ export interface ErrorLoad<
162
+ Params extends Record<string, string> = Record<string, string>,
163
+ Props extends Record<string, any> = Record<string, any>
164
+ > {
162
165
  (input: ErrorLoadInput<Params>): MaybePromise<LoadOutput<Props>>;
163
166
  }
164
167
 
@@ -218,11 +221,14 @@ export interface Page<Params extends Record<string, string> = Record<string, str
218
221
  * Note that you can use [generated types](/docs/types#generated-types)
219
222
  * instead of manually specifying the `Params` generic argument.
220
223
  */
221
- export interface RequestHandler<Params = Record<string, string>, Output extends Body = Body> {
224
+ export interface RequestHandler<
225
+ Params extends Record<string, string> = Record<string, string>,
226
+ Output extends ResponseBody = ResponseBody
227
+ > {
222
228
  (event: RequestEvent<Params>): RequestHandlerOutput<Output>;
223
229
  }
224
230
 
225
- export type RequestHandlerOutput<Output extends Body = Body> = MaybePromise<
231
+ export type RequestHandlerOutput<Output extends ResponseBody = ResponseBody> = MaybePromise<
226
232
  Either<
227
233
  {
228
234
  status?: number;
@@ -233,9 +239,11 @@ export type RequestHandlerOutput<Output extends Body = Body> = MaybePromise<
233
239
  >
234
240
  >;
235
241
 
242
+ export type ResponseBody = JSONValue | Uint8Array | ReadableStream | import('stream').Readable;
243
+
236
244
  export class Server {
237
245
  constructor(manifest: SSRManifest);
238
- respond(request: Request, options?: RequestOptions): Promise<Response>;
246
+ respond(request: Request, options: RequestOptions): Promise<Response>;
239
247
  }
240
248
 
241
249
  export interface SSRManifest {
@@ -92,7 +92,7 @@ export interface Hooks {
92
92
  export class InternalServer extends Server {
93
93
  respond(
94
94
  request: Request,
95
- options?: RequestOptions & {
95
+ options: RequestOptions & {
96
96
  prerender?: PrerenderOptions;
97
97
  }
98
98
  ): Promise<Response>;
@@ -164,7 +164,7 @@ export type RecursiveRequired<T> = {
164
164
  export type RequiredResolveOptions = Required<ResolveOptions>;
165
165
 
166
166
  export interface Respond {
167
- (request: Request, options: SSROptions, state?: SSRState): Promise<Response>;
167
+ (request: Request, options: SSROptions, state: SSRState): Promise<Response>;
168
168
  }
169
169
 
170
170
  export type RouteData = PageData | EndpointData;
@@ -302,11 +302,12 @@ export interface SSRPagePart {
302
302
  export type SSRRoute = SSREndpoint | SSRPage;
303
303
 
304
304
  export interface SSRState {
305
+ fallback?: string;
305
306
  fetched?: string;
307
+ getClientAddress: () => string;
306
308
  initiator?: SSRPage | null;
307
309
  platform?: any;
308
310
  prerender?: PrerenderOptions;
309
- fallback?: string;
310
311
  }
311
312
 
312
313
  export type StrictBody = string | Uint8Array;
@@ -28,8 +28,6 @@ export interface AdapterEntry {
28
28
  }) => void;
29
29
  }
30
30
 
31
- export type Body = JSONValue | Uint8Array | ReadableStream | import('stream').Readable;
32
-
33
31
  // Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts
34
32
  //
35
33
  // MIT License
@@ -140,7 +138,8 @@ export interface CspDirectives {
140
138
 
141
139
  export type Either<T, U> = Only<T, U> | Only<U, T>;
142
140
 
143
- export interface ErrorLoadInput<Params = Record<string, string>> extends LoadInput<Params> {
141
+ export interface ErrorLoadInput<Params extends Record<string, string> = Record<string, string>>
142
+ extends LoadInput<Params> {
144
143
  status?: number;
145
144
  error?: Error;
146
145
  }
@@ -165,7 +164,10 @@ export type JSONValue =
165
164
  | JSONValue[]
166
165
  | JSONObject;
167
166
 
168
- export interface LoadInput<Params = Record<string, string>, Props = Record<string, any>> {
167
+ export interface LoadInput<
168
+ Params extends Record<string, string> = Record<string, string>,
169
+ Props extends Record<string, any> = Record<string, any>
170
+ > {
169
171
  url: URL;
170
172
  params: Params;
171
173
  props: Props;
@@ -174,7 +176,7 @@ export interface LoadInput<Params = Record<string, string>, Props = Record<strin
174
176
  stuff: Partial<App.Stuff>;
175
177
  }
176
178
 
177
- export interface LoadOutput<Props = Record<string, any>> {
179
+ export interface LoadOutput<Props extends Record<string, any> = Record<string, any>> {
178
180
  status?: number;
179
181
  error?: string | Error;
180
182
  redirect?: string;
@@ -233,15 +235,17 @@ export interface PrerenderErrorHandler {
233
235
 
234
236
  export type PrerenderOnErrorValue = 'fail' | 'continue' | PrerenderErrorHandler;
235
237
 
236
- export interface RequestEvent<Params = Record<string, string>> {
237
- request: Request;
238
- url: URL;
239
- params: Params;
238
+ export interface RequestEvent<Params extends Record<string, string> = Record<string, string>> {
239
+ clientAddress: string;
240
240
  locals: App.Locals;
241
+ params: Params;
241
242
  platform: Readonly<App.Platform>;
243
+ request: Request;
244
+ url: URL;
242
245
  }
243
246
 
244
247
  export interface RequestOptions {
248
+ getClientAddress: () => string;
245
249
  platform?: App.Platform;
246
250
  }
247
251