Repository: sveltejs/kit (js)

Issue:
"parent is not a function" when requesting page endpoint
### Describe the bug

Requesting a `+page.server.ts` endpoint to do a GET request works, but fails if an await for parent data is added to it.

### Reproduction

Add `\+layout.server.ts`:

```ts
import type { LayoutServerLoad } from "./$types";

export const load: LayoutServerLoad = async ({ }) => {
  return {
    site: 'My Site'
  }
}
```

Add `\+page.server.ts`:

```ts
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async ({ parent }) => {
  const site = await parent()

  return {
    ...site,
    name: 'test'
  }
}
```

Request page with `accept: application/json` http header.

### Logs

```shell
parent is not a function
TypeError: parent is not a function
    at load (/Users/simon/dev/temp/sk-411/src/routes/+page.server.ts:5:21)
    at handle_json_request (file:///Users/simon/dev/temp/sk-411/node_modules/.pnpm/@sveltejs+kit@1.0.0-next.411_svelte@3.49.0+vite@3.0.8/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:357:32)
    at render_page (file:///Users/simon/dev/temp/sk-411/node_modules/.pnpm/@sveltejs+kit@1.0.0-next.411_svelte@3.49.0+vite@3.0.8/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:42:11)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async resolve (file:///Users/simon/dev/temp/sk-411/node_modules/.pnpm/@sveltejs+kit@1.0.0-next.411_svelte@3.49.0+vite@3.0.8/node_modules/@sveltejs/kit/src/runtime/server/index.js:308:11)
    at async respond (file:///Users/simon/dev/temp/sk-411/node_modules/.pnpm/@sveltejs+kit@1.0.0-next.411_svelte@3.49.0+vite@3.0.8/node_modules/@sveltejs/kit/src/runtime/server/index.js:202:20)
    at async file:///Users/simon/dev/temp/sk-411/node_modules/.pnpm/@sveltejs+kit@1.0.0-next.411_svelte@3.49.0+vite@3.0.8/node_modules/@sveltejs/kit/src/vite/dev/index.js:396:22
```


### System Info

```shell
System:
    OS: macOS 12.5
    CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
    Memory: 951.54 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.0 - /usr/local/bin/node
    npm: 8.3.1 - /usr/local/bin/npm
  Browsers:
    Brave Browser: 102.1.39.111
    Chrome: 104.0.5112.79
    Chrome Canary: 106.0.5243.0
    Firefox: 103.0.2
    Safari: 15.6
    Safari Technology Preview: 16.0
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.64 
    @sveltejs/kit: next => 1.0.0-next.411 
    svelte: ^3.44.0 => 3.49.0 
    vite: ^3.0.0 => 3.0.8
```


### Severity

blocking an upgrade

### Additional Information

_No response_

Pull request description:
remove ability for +page.server.js to respond to GET requests with JSON
Closes #5936. This behaviour is nothing more than a historical accident. It's buggy, and there's no reason to keep it.

If we want routes to serve both HTML and non-HTML, #5896 is a more promising approach.

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/few-hornets-joke.md b/.changeset/few-hornets-joke.md
new file mode 100644
index 000000000..e1d391fa9
--- /dev/null
+++ b/.changeset/few-hornets-joke.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Respect `export const prerender = false` in `+page.server.js`
diff --git a/.changeset/fresh-pigs-tease.md b/.changeset/fresh-pigs-tease.md
new file mode 100644
index 000000000..9af327627
--- /dev/null
+++ b/.changeset/fresh-pigs-tease.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+[breaking] remove ability for `+page.server.js` to respond to `GET` requests with JSON
diff --git a/.changeset/gold-rocks-hang.md b/.changeset/gold-rocks-hang.md
new file mode 100644
index 000000000..03fd306e9
--- /dev/null
+++ b/.changeset/gold-rocks-hang.md
@@ -0,0 +1,5 @@
+---
+'create-svelte': patch
+---
+
+update `app.d.ts` for library skeleton template
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 58258eebe..ea7fe6e55 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -256,6 +256,7 @@
     "few-buses-argue",
     "few-carrots-sell",
     "few-cobras-switch",
+    "few-hornets-joke",
     "few-points-taste",
     "few-rockets-sort",
     "few-rockets-think",
@@ -335,6 +336,7 @@
     "gold-carrots-sniff",
     "gold-colts-train",
     "gold-moles-hunt",
+    "gold-rocks-hang",
     "gold-spies-fail",
     "gold-trains-dream",
     "good-beans-invite",
diff --git a/documentation/docs/15-configuration.md b/documentation/docs/15-configuration.md
index 844ba60b3..2f99bd282 100644
--- a/documentation/docs/15-configuration.md
+++ b/documentation/docs/15-configuration.md
@@ -72,9 +72,6 @@ const config = {
 		}
 	},
 
-	// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
-	preprocess: null,
-
 	// options passed to @sveltejs/package
 	package: {
 		source: 'value of kit.files.lib, if available, else src/lib',
@@ -83,7 +80,10 @@ const config = {
 		// excludes all .d.ts and files starting with _ as the name
 		exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
 		files: () => true
-	}
+	},
+
+	// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
+	preprocess: null
 };
 
 export default config;
diff --git a/packages/create-svelte/CHANGELOG.md b/packages/create-svelte/CHANGELOG.md
index dbdb840a5..f03c4fa56 100644
--- a/packages/create-svelte/CHANGELOG.md
+++ b/packages/create-svelte/CHANGELOG.md
@@ -1,5 +1,11 @@
 # create-svelte
 
+## 2.0.0-next.156
+
+### Patch Changes
+
+- update `app.d.ts` for library skeleton template ([#6020](https://github.com/sveltejs/kit/pull/6020))
+
 ## 2.0.0-next.155
 
 ### Patch Changes
diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json
index ca8f89dce..56e941bcc 100644
--- a/packages/create-svelte/package.json
+++ b/packages/create-svelte/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "create-svelte",
-	"version": "2.0.0-next.155",
+	"version": "2.0.0-next.156",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/create-svelte/templates/libskeleton/src/app.d.ts b/packages/create-svelte/templates/libskeleton/src/app.d.ts
index b28d84056..66327cbb1 100644
--- a/packages/create-svelte/templates/libskeleton/src/app.d.ts
+++ b/packages/create-svelte/templates/libskeleton/src/app.d.ts
@@ -6,6 +6,6 @@
 declare namespace App {
 	// interface Locals {}
 	// interface Platform {}
-	// interface Session {}
-	// interface Stuff {}
+	// interface PrivateEnv {}
+	// interface PublicEnv {}
 }
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index 7b859cf14..fdef39d3d 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/kit
 
+## 1.0.0-next.421
+
+### Patch Changes
+
+- Respect `export const prerender = false` in `+page.server.js` ([#6012](https://github.com/sveltejs/kit/pull/6012))
+
 ## 1.0.0-next.420
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index 664069a66..3645e8c6a 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.0.0-next.420",
+	"version": "1.0.0-next.421",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js
index a7f6acf2c..91f0a6470 100644
--- a/packages/kit/src/runtime/server/page/index.js
+++ b/packages/kit/src/runtime/server/page/index.js
@@ -36,7 +36,11 @@ export async function render_page(event, route, options, state, resolve_opts) {
 		'application/json'
 	]);
 
-	if (accept === 'application/json') {
+	if (
+		accept === 'application/json' &&
+		event.request.method !== 'GET' &&
+		event.request.method !== 'HEAD'
+	) {
 		const node = await options.manifest._.nodes[route.leaf]();
 		if (node.server) {
 			return handle_json_request(event, options, node.server);
@@ -117,7 +121,8 @@ export async function render_page(event, route, options, state, resolve_opts) {
 			});
 		}
 
-		const should_prerender = leaf_node.shared?.prerender ?? options.prerender.default;
+		const should_prerender =
+			leaf_node.shared?.prerender ?? leaf_node.server?.prerender ?? options.prerender.default;
 		if (should_prerender) {
 			const mod = leaf_node.server;
 			if (mod && (mod.POST || mod.PUT || mod.DELETE || mod.PATCH)) {
@@ -345,8 +350,8 @@ function get_page_config(leaf, options) {
  * @param {import('types').SSRNode['server']} mod
  */
 export async function handle_json_request(event, options, mod) {
-	const method = /** @type {import('types').HttpMethod} */ (event.request.method);
-	const handler = mod[method === 'HEAD' || method === 'GET' ? 'load' : method];
+	const method = /** @type {'POST' | 'PUT' | 'PATCH' | 'DELETE'} */ (event.request.method);
+	const handler = mod[method];
 
 	if (!handler) {
 		return method_not_allowed(mod, method);
@@ -356,14 +361,6 @@ export async function handle_json_request(event, options, mod) {
 		// @ts-ignore
 		const result = await handler.call(null, event);
 
-		if (method === 'HEAD') {
-			return new Response();
-		}
-
-		if (method === 'GET') {
-			return json(result);
-		}
-
 		if (result?.errors) {
 			// @ts-ignore
 			return json({ errors: result.errors }, { status: result.status || 400 });
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index 4e63561ca..44b15f463 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -106,7 +106,6 @@ export interface Config {
 	compilerOptions?: CompileOptions;
 	extensions?: string[];
 	kit?: KitConfig;
-	preprocess?: any;
 	package?: {
 		source?: string;
 		dir?: string;
@@ -114,6 +113,7 @@ export interface Config {
 		exports?: (filepath: string) => boolean;
 		files?: (filepath: string) => boolean;
 	};
+	preprocess?: any;
 	[key: string]: any;
 }
 
diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts
index 9738ab5a0..4f386bab0 100644
--- a/packages/kit/types/internal.d.ts
+++ b/packages/kit/types/internal.d.ts
@@ -211,12 +211,11 @@ export interface SSRNode {
 		hydrate?: boolean;
 		prerender?: boolean;
 		router?: boolean;
-		ssr?: boolean;
 	};
 
 	server: {
 		load?: ServerLoad;
-		HEAD?: ServerLoad;
+		prerender?: boolean;
 		POST?: Action;
 		PATCH?: Action;
 		PUT?: Action;
diff --git a/packages/package/src/types.d.ts b/packages/package/src/types.d.ts
index f08999f8c..2350e43f3 100644
--- a/packages/package/src/types.d.ts
+++ b/packages/package/src/types.d.ts
@@ -18,10 +18,10 @@ export type RecursiveRequired<T> = {
 };
 
 export interface ValidatedConfig {
-	preprocess?: any;
 	extensions: string[];
-	package: RecursiveRequired<PackageConfig>;
 	kit?: any;
+	package: RecursiveRequired<PackageConfig>;
+	preprocess?: any;
 }
 
 export type Validator<T = any> = (input: T, keypath: string) => T;
diff --git a/packages/package/types/index.d.ts b/packages/package/types/index.d.ts
index 07670d36b..0e1ba39b6 100644
--- a/packages/package/types/index.d.ts
+++ b/packages/package/types/index.d.ts
@@ -29,6 +29,6 @@ export interface Config {
 	compilerOptions?: CompileOptions;
 	extensions?: string[];
 	kit?: any;
-	preprocess?: any;
 	package?: PackageConfig;
+	preprocess?: any;
 }


Test patch:
diff --git a/packages/kit/test/apps/basics/test/server.test.js b/packages/kit/test/apps/basics/test/server.test.js
index 45615bcb5..539731fad 100644
--- a/packages/kit/test/apps/basics/test/server.test.js
+++ b/packages/kit/test/apps/basics/test/server.test.js
@@ -124,40 +124,6 @@ test.describe('Errors', () => {
 		expect(await response.text()).toMatch('thisvariableisnotdefined is not defined');
 	});
 
-	test('page endpoint thrown error respects `accept: application/json`', async ({ request }) => {
-		const response = await request.get('/errors/page-endpoint/get-implicit', {
-			headers: {
-				accept: 'application/json'
-			}
-		});
-
-		const { message, name, stack, fancy } = await response.json();
-
-		expect(response.status()).toBe(500);
-		expect(name).toBe('FancyError');
-		expect(message).toBe('oops');
-		expect(fancy).toBe(true);
-
-		if (process.env.DEV) {
-			expect(stack.split('\n').length).toBeGreaterThan(1);
-		} else {
-			expect(stack.split('\n').length).toBe(1);
-		}
-	});
-
-	test('page endpoint returned error respects `accept: application/json`', async ({ request }) => {
-		const response = await request.get('/errors/page-endpoint/get-explicit', {
-			headers: {
-				accept: 'application/json'
-			}
-		});
-
-		const { message } = await response.json();
-
-		expect(response.status()).toBe(400);
-		expect(message).toBe('oops');
-	});
-
 	test('returns 400 when accessing a malformed URI', async ({ page }) => {
 		const response = await page.goto('/%c0%ae%c0%ae/etc/passwd');
 		if (process.env.DEV) {
@@ -211,53 +177,6 @@ test.describe('Routing', () => {
 });
 
 test.describe('Shadowed pages', () => {
-	test('responds to HEAD requests from endpoint', async ({ request }) => {
-		const url = '/shadowed/simple';
-
-		const opts = {
-			headers: {
-				accept: 'application/json'
-			}
-		};
-
-		const responses = {
-			head: await request.head(url, opts),
-			get: await request.get(url, opts)
-		};
-
-		const headers = {
-			head: responses.head.headers(),
-			get: responses.get.headers()
-		};
-
-		expect(responses.head.status()).toBe(200);
-		expect(responses.get.status()).toBe(200);
-		expect(await responses.head.text()).toBe('');
-		expect(await responses.get.json()).toEqual({ answer: 42 });
-
-		['date', 'transfer-encoding'].forEach((name) => {
-			delete headers.head[name];
-			delete headers.get[name];
-		});
-
-		expect(headers.get).toEqual({
-			...headers.head,
-			'content-type': 'application/json'
-		});
-	});
-
-	test('Responds from endpoint if Accept includes application/json but not text/html', async ({
-		request
-	}) => {
-		const response = await request.get('/shadowed/simple', {
-			headers: {
-				accept: 'application/json'
-			}
-		});
-
-		expect(await response.json()).toEqual({ answer: 42 });
-	});
-
 	test('Action can return undefined', async ({ request }) => {
 		const response = await request.post('/shadowed/simple/post', {
 			headers: {
diff --git a/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.server.js b/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.server.js
new file mode 100644
index 000000000..d43d0cd2a
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.server.js
@@ -0,0 +1,1 @@
+export const prerender = false;
diff --git a/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.svelte b/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.svelte
new file mode 100644
index 000000000..3c3d6df7a
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/src/routes/page-server-options/+page.svelte
@@ -0,0 +1,1 @@
+<h1>This should not be visible</h1>
diff --git a/packages/kit/test/prerendering/basics/test/test.js b/packages/kit/test/prerendering/basics/test/test.js
index 6a213c913..e79573f0f 100644
--- a/packages/kit/test/prerendering/basics/test/test.js
+++ b/packages/kit/test/prerendering/basics/test/test.js
@@ -99,6 +99,11 @@ test('does not prerender page with shadow endpoint with non-load handler', () =>
 	assert.ok(!fs.existsSync(`${build}/shadowed-post/__data.json`));
 });
 
+test('does not prerender page with prerender = false in +page.server.js', () => {
+	assert.ok(!fs.existsSync(`${build}/page-server-options.html`));
+	assert.ok(!fs.existsSync(`${build}/page-server-options/__data.json`));
+});
+
 test('decodes paths when writing files', () => {
 	let content = read('encoding/path with spaces.html');
 	assert.ok(content.includes('<p id="a">path with spaces</p>'));