Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Do not reference any internal types in runtime/index.d.ts #1604

Merged
merged 12 commits into from
Oct 23, 2020
75 changes: 69 additions & 6 deletions runtime/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*
* This file declares all Sapper types that are accessible to project code.
* It is created in src/node_modules/@sapper in projects during the build.
* It must not import any internal Sapper types as it will not be possible for
* project code to reference those.
*/

declare module '@sapper/app' {
export interface Redirect {
statusCode: number
Expand All @@ -12,16 +19,64 @@ declare module '@sapper/app' {
}

declare module '@sapper/server' {
import { Handler, Req, Res } from '@sapper/internal/manifest-server';
import { IncomingMessage, ServerResponse } from 'http';
import { TLSSocket } from 'tls';

export type Ignore = string | RegExp | ((uri: string) => boolean) | Ignore[];

/**
* The request object passed to middleware and server-side routes.
* These fields are common to both Polka and Express, but you are free to
* instead use the typings that come with the server you use.
*/
export interface Req extends IncomingMessage {
benmccann marked this conversation as resolved.
Show resolved Hide resolved
url: string;
method: string;
baseUrl: string;

/**
* The originally requested URL, including parent router segments.
*/
originalUrl: string;

/**
* The path portion of the requested URL.
*/
path: string;

/**
* The values of named parameters within your route pattern
*/
params: Record<string, string>;

/**
* The un-parsed querystring
*/
search: string | null;

/**
* The parsed querystring
*/
query: Record<string, string>;

socket: TLSSocket;
}

export interface Res extends ServerResponse {
locals?: {
nonce?: string;
name?: string;
};
}

export interface MiddlewareOptions {
session?: (req: Req, res: Res) => unknown
ignore?: Ignore
session?: (req: Req, res: Res) => unknown;
ignore?: Ignore;
}

export function middleware(opts: MiddlewareOptions): Handler;
export function middleware(
opts: MiddlewareOptions
ehrencrona marked this conversation as resolved.
Show resolved Hide resolved
): (req: Req, res: Res, next: () => void) => void;
}

declare module '@sapper/service-worker' {
Expand All @@ -39,15 +94,23 @@ declare module '@sapper/common' {
redirect: (statusCode: number, location: string) => void;
}

export interface Page {
export interface PageContext {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably rather save the nice name Page for external usage and rename the internal Page type to something like PageInfo

Copy link
Contributor Author

@ehrencrona ehrencrona Oct 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine with that, but I generally feel this isn't a "page". The page parameters really parametrize a route, so I guess a page is more or less the same as a route, This object is attached to a request, whereas a page feels like something more permanent, at least to me.

How about PageRequest ("a request for a page")? The request carries the parameters for the page, the PageParams. That kind of makes sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a PageRequest because of the error. I guess PageContext makes sense

host: string;
path: string;
params: Record<string, string>;
query: Record<string, string | string[]>;
/** `error` is only set when the error page is being rendered. */
error?: Error;
}

/**
* @deprecated PageContext is the preferred name. Page might be removed in the future.
*/
export { PageContext as Page };

export type PreloadResult = object | Promise<object>

export interface Preload {
(this: PreloadContext, page: Page, session: any): object | Promise<object>;
(this: PreloadContext, page: PageContext, session: any): PreloadResult;
}
}
2 changes: 1 addition & 1 deletion runtime/src/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import {
Redirect,
Branch,
Page,
PageContext,
InitialData
} from './types';
import { PageContext } from '@sapper/common';
import goto from './goto';
import { page_store } from './stores';

Expand Down
5 changes: 2 additions & 3 deletions runtime/src/app/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ignore,
routes
} from '@sapper/internal/manifest-client';
import { Query } from '@sapper/internal/shared';
import find_anchor from './find_anchor';

export let uid = 1;
Expand Down Expand Up @@ -68,7 +67,7 @@ export function init(base: string, handler: (dest: Target) => Promise<void>): vo
}

export function extract_query(search: string) {
const query = Object.create(null);
const query: Record<string, string | string[]> = Object.create(null);
benmccann marked this conversation as resolved.
Show resolved Hide resolved
if (search.length > 0) {
search.slice(1).split('&').forEach(searchParam => {
const [, key, value = ''] = /([^=]*)(?:=(.*))?/.exec(decodeURIComponent(searchParam.replace(/\+/g, ' ')));
Expand Down Expand Up @@ -99,7 +98,7 @@ export function select_target(url: URL): Target {
const match = route.pattern.exec(path);

if (match) {
const query: Query = extract_query(url.search);
const query = extract_query(url.search);
const part = route.parts[route.parts.length - 1];
const params = part.params ? part.params(match) : {};

Expand Down
8 changes: 0 additions & 8 deletions runtime/src/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,3 @@ export interface Page {
params: Record<string, string>;
query: Record<string, string | string[]>;
}

/**
* Information about the current page in the `page` store.
*/
export interface PageContext extends Page {
/** `error` is only set when the error page is being rendered. */
error?: Error;
}
6 changes: 6 additions & 0 deletions runtime/src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* This file exists to avoid errors on references to @sapper/common from inside Sapper.
* (@sapper/common is a namespace defined in index.d.ts)
*/

export default null;
24 changes: 2 additions & 22 deletions runtime/src/internal/manifest-server.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { ClientRequest, ServerResponse } from 'http';
import { TLSSocket } from 'tls';
import {
Preload
} from './shared';
Expand All @@ -9,6 +7,8 @@ export const build_dir: string;
export const dev: boolean;
export const manifest: Manifest;

export { Req, Res } from '@sapper/server';

export interface SSRComponentModule {
default: SSRComponent;
preload?: Preload;
Expand Down Expand Up @@ -44,26 +44,6 @@ export interface ManifestPagePart {

export type Handler = (req: Req, res: Res, next: () => void) => void;

export interface Req extends ClientRequest {
url: string;
baseUrl: string;
originalUrl: string;
method: string;
path: string;
params: Record<string, string>;
query: Record<string, string>;
headers: Record<string, string>;
socket: TLSSocket;
}

export interface Res extends ServerResponse {
write: (data: any) => boolean;
locals?: {
nonce?: string;
name?: string;
};
}

export interface ServerRoute {
pattern: RegExp;
handlers: Record<string, Handler>;
Expand Down
7 changes: 0 additions & 7 deletions runtime/src/internal/shared.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
export const CONTEXT_KEY: unknown;

export type Params = Record<string, string>;
export type Query = Record<string, string | string[]>;
export type PreloadResult = object | Promise<object>;
export interface Preload {
(this: PreloadContext, page: PreloadPage, session: any): PreloadResult;
}
3 changes: 1 addition & 2 deletions runtime/src/server/middleware/get_page_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import fetch from 'node-fetch';
import URL from 'url';
import { sourcemap_stacktrace } from './sourcemap_stacktrace';
import { Manifest, ManifestPage, Req, Res, build_dir, dev, src_dir } from '@sapper/internal/manifest-server';
import { PreloadResult } from '@sapper/internal/shared';
import App from '@sapper/internal/App.svelte';
import { PageContext } from '@sapper/app/types';
import { PageContext, PreloadResult } from '@sapper/common';

export function get_page_handler(
manifest: Manifest,
Expand Down
9 changes: 9 additions & 0 deletions site/content/docs/02-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ export async function get(req, res, next) {

> `delete` is a reserved word in JavaScript. To handle DELETE requests, export a function called `del` instead.

If you are using TypeScript, use the following types:

```js
import { Req, Res } from '@sapper/server';

function get(req: Req, res: Res, next: () => void) { ... }
```

`Req` and `Res` will work with both Polka and Express. You can replace them with the types specific to your server, which are `polka.Request` / `http.ServerResponse` and `express.Request` / `express.Response`, respectively.

### File naming rules

Expand Down