UNPKG

21.4 kBTypeScriptView Raw
1// Type definitions for Koa 2.13.1
2// Project: http://koajs.com
3// Definitions by: jKey Lu <https://github.com/jkeylu>
4// Brice Bernard <https://github.com/brikou>
5// harryparkdotio <https://github.com/harryparkdotio>
6// Wooram Jun <https://github.com/chatoo2412>
7// Christian Vaagland Tellnes <https://github.com/tellnes>
8// Piotr Kuczynski <https://github.com/pkuczynski>
9// vnoder <https://github.com/vnoder>
10// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
11// TypeScript Version: 3.0
12
13/* =================== USAGE ===================
14
15 import * as Koa from "koa"
16 const app = new Koa()
17
18 async function (ctx: Koa.Context, next: Koa.Next) {
19 // ...
20 }
21
22 =============================================== */
23/// <reference types="node" />
24import * as accepts from "accepts";
25import * as Cookies from "cookies";
26import { EventEmitter } from "events";
27import { IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, Server, ServerResponse } from "http";
28import { Http2ServerRequest, Http2ServerResponse } from "http2";
29import httpAssert = require("http-assert");
30import * as contentDisposition from "content-disposition";
31import * as HttpErrors from "http-errors";
32import * as Keygrip from "keygrip";
33import * as compose from "koa-compose";
34import { ListenOptions, Socket } from "net";
35import { ParsedUrlQuery } from "querystring";
36import * as url from "url";
37
38declare interface ContextDelegatedRequest {
39 /**
40 * Return request header.
41 */
42 header: IncomingHttpHeaders;
43
44 /**
45 * Return request header, alias as request.header
46 */
47 headers: IncomingHttpHeaders;
48
49 /**
50 * Get/Set request URL.
51 */
52 url: string;
53
54 /**
55 * Get origin of URL.
56 */
57 origin: string;
58
59 /**
60 * Get full request URL.
61 */
62 href: string;
63
64 /**
65 * Get/Set request method.
66 */
67 method: string;
68
69 /**
70 * Get request pathname.
71 * Set pathname, retaining the query-string when present.
72 */
73 path: string;
74
75 /**
76 * Get parsed query-string.
77 * Set query-string as an object.
78 */
79 query: ParsedUrlQuery;
80
81 /**
82 * Get/Set query string.
83 */
84 querystring: string;
85
86 /**
87 * Get the search string. Same as the querystring
88 * except it includes the leading ?.
89 *
90 * Set the search string. Same as
91 * response.querystring= but included for ubiquity.
92 */
93 search: string;
94
95 /**
96 * Parse the "Host" header field host
97 * and support X-Forwarded-Host when a
98 * proxy is enabled.
99 */
100 host: string;
101
102 /**
103 * Parse the "Host" header field hostname
104 * and support X-Forwarded-Host when a
105 * proxy is enabled.
106 */
107 hostname: string;
108
109 /**
110 * Get WHATWG parsed URL object.
111 */
112 URL: url.URL;
113
114 /**
115 * Check if the request is fresh, aka
116 * Last-Modified and/or the ETag
117 * still match.
118 */
119 fresh: boolean;
120
121 /**
122 * Check if the request is stale, aka
123 * "Last-Modified" and / or the "ETag" for the
124 * resource has changed.
125 */
126 stale: boolean;
127
128 /**
129 * Check if the request is idempotent.
130 */
131 idempotent: boolean;
132
133 /**
134 * Return the request socket.
135 */
136 socket: Socket;
137
138 /**
139 * Return the protocol string "http" or "https"
140 * when requested with TLS. When the proxy setting
141 * is enabled the "X-Forwarded-Proto" header
142 * field will be trusted. If you're running behind
143 * a reverse proxy that supplies https for you this
144 * may be enabled.
145 */
146 protocol: string;
147
148 /**
149 * Short-hand for:
150 *
151 * this.protocol == 'https'
152 */
153 secure: boolean;
154
155 /**
156 * Request remote address. Supports X-Forwarded-For when app.proxy is true.
157 */
158 ip: string;
159
160 /**
161 * When `app.proxy` is `true`, parse
162 * the "X-Forwarded-For" ip address list.
163 *
164 * For example if the value were "client, proxy1, proxy2"
165 * you would receive the array `["client", "proxy1", "proxy2"]`
166 * where "proxy2" is the furthest down-stream.
167 */
168 ips: string[];
169
170 /**
171 * Return subdomains as an array.
172 *
173 * Subdomains are the dot-separated parts of the host before the main domain
174 * of the app. By default, the domain of the app is assumed to be the last two
175 * parts of the host. This can be changed by setting `app.subdomainOffset`.
176 *
177 * For example, if the domain is "tobi.ferrets.example.com":
178 * If `app.subdomainOffset` is not set, this.subdomains is
179 * `["ferrets", "tobi"]`.
180 * If `app.subdomainOffset` is 3, this.subdomains is `["tobi"]`.
181 */
182 subdomains: string[];
183
184 /**
185 * Check if the given `type(s)` is acceptable, returning
186 * the best match when true, otherwise `false`, in which
187 * case you should respond with 406 "Not Acceptable".
188 *
189 * The `type` value may be a single mime type string
190 * such as "application/json", the extension name
191 * such as "json" or an array `["json", "html", "text/plain"]`. When a list
192 * or array is given the _best_ match, if any is returned.
193 *
194 * Examples:
195 *
196 * // Accept: text/html
197 * this.accepts('html');
198 * // => "html"
199 *
200 * // Accept: text/*, application/json
201 * this.accepts('html');
202 * // => "html"
203 * this.accepts('text/html');
204 * // => "text/html"
205 * this.accepts('json', 'text');
206 * // => "json"
207 * this.accepts('application/json');
208 * // => "application/json"
209 *
210 * // Accept: text/*, application/json
211 * this.accepts('image/png');
212 * this.accepts('png');
213 * // => undefined
214 *
215 * // Accept: text/*;q=.5, application/json
216 * this.accepts(['html', 'json']);
217 * this.accepts('html', 'json');
218 * // => "json"
219 */
220 accepts(): string[];
221 accepts(...types: string[]): string | false;
222 accepts(types: string[]): string | false;
223
224 /**
225 * Return accepted encodings or best fit based on `encodings`.
226 *
227 * Given `Accept-Encoding: gzip, deflate`
228 * an array sorted by quality is returned:
229 *
230 * ['gzip', 'deflate']
231 */
232 acceptsEncodings(): string[];
233 acceptsEncodings(...encodings: string[]): string | false;
234 acceptsEncodings(encodings: string[]): string | false;
235
236 /**
237 * Return accepted charsets or best fit based on `charsets`.
238 *
239 * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
240 * an array sorted by quality is returned:
241 *
242 * ['utf-8', 'utf-7', 'iso-8859-1']
243 */
244 acceptsCharsets(): string[];
245 acceptsCharsets(...charsets: string[]): string | false;
246 acceptsCharsets(charsets: string[]): string | false;
247
248 /**
249 * Return accepted languages or best fit based on `langs`.
250 *
251 * Given `Accept-Language: en;q=0.8, es, pt`
252 * an array sorted by quality is returned:
253 *
254 * ['es', 'pt', 'en']
255 */
256 acceptsLanguages(): string[];
257 acceptsLanguages(...langs: string[]): string | false;
258 acceptsLanguages(langs: string[]): string | false;
259
260 /**
261 * Check if the incoming request contains the "Content-Type"
262 * header field, and it contains any of the give mime `type`s.
263 * If there is no request body, `null` is returned.
264 * If there is no content type, `false` is returned.
265 * Otherwise, it returns the first `type` that matches.
266 *
267 * Examples:
268 *
269 * // With Content-Type: text/html; charset=utf-8
270 * this.is('html'); // => 'html'
271 * this.is('text/html'); // => 'text/html'
272 * this.is('text/*', 'application/json'); // => 'text/html'
273 *
274 * // When Content-Type is application/json
275 * this.is('json', 'urlencoded'); // => 'json'
276 * this.is('application/json'); // => 'application/json'
277 * this.is('html', 'application/*'); // => 'application/json'
278 *
279 * this.is('html'); // => false
280 */
281 // is(): string | boolean;
282 is(...types: string[]): string | false | null;
283 is(types: string[]): string | false | null;
284
285 /**
286 * Return request header. If the header is not set, will return an empty
287 * string.
288 *
289 * The `Referrer` header field is special-cased, both `Referrer` and
290 * `Referer` are interchangeable.
291 *
292 * Examples:
293 *
294 * this.get('Content-Type');
295 * // => "text/plain"
296 *
297 * this.get('content-type');
298 * // => "text/plain"
299 *
300 * this.get('Something');
301 * // => ''
302 */
303 get(field: string): string;
304}
305
306declare interface ContextDelegatedResponse {
307 /**
308 * Get/Set response status code.
309 */
310 status: number;
311
312 /**
313 * Get response status message
314 */
315 message: string;
316
317 /**
318 * Get/Set response body.
319 */
320 body: unknown;
321
322 /**
323 * Return parsed response Content-Length when present.
324 * Set Content-Length field to `n`.
325 */
326 length: number;
327
328 /**
329 * Check if a header has been written to the socket.
330 */
331 headerSent: boolean;
332
333 /**
334 * Vary on `field`.
335 */
336 vary(field: string | string[]): void;
337
338 /**
339 * Perform a 302 redirect to `url`.
340 *
341 * The string "back" is special-cased
342 * to provide Referrer support, when Referrer
343 * is not present `alt` or "/" is used.
344 *
345 * Examples:
346 *
347 * this.redirect('back');
348 * this.redirect('back', '/index.html');
349 * this.redirect('/login');
350 * this.redirect('http://google.com');
351 */
352 redirect(url: string, alt?: string): void;
353
354 /**
355 * Set Content-Disposition to "attachment" to signal the client to prompt for download.
356 * Optionally specify the filename of the download and some options.
357 */
358 attachment(filename?: string, options?: contentDisposition.Options): void;
359
360 /**
361 * Return the response mime type void of
362 * parameters such as "charset".
363 *
364 * Set Content-Type response header with `type` through `mime.lookup()`
365 * when it does not contain a charset.
366 *
367 * Examples:
368 *
369 * this.type = '.html';
370 * this.type = 'html';
371 * this.type = 'json';
372 * this.type = 'application/json';
373 * this.type = 'png';
374 */
375 type: string;
376
377 /**
378 * Get the Last-Modified date in Date form, if it exists.
379 * Set the Last-Modified date using a string or a Date.
380 *
381 * this.response.lastModified = new Date();
382 * this.response.lastModified = '2013-09-13';
383 */
384 lastModified: Date;
385
386 /**
387 * Get/Set the ETag of a response.
388 * This will normalize the quotes if necessary.
389 *
390 * this.response.etag = 'md5hashsum';
391 * this.response.etag = '"md5hashsum"';
392 * this.response.etag = 'W/"123456789"';
393 *
394 * @param {String} etag
395 * @api public
396 */
397 etag: string;
398
399 /**
400 * Set header `field` to `val`, or pass
401 * an object of header fields.
402 *
403 * Examples:
404 *
405 * this.set('Foo', ['bar', 'baz']);
406 * this.set('Accept', 'application/json');
407 * this.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
408 */
409 set(field: { [key: string]: string | string[] }): void;
410 set(field: string, val: string | string[]): void;
411
412 /**
413 * Append additional header `field` with value `val`.
414 *
415 * Examples:
416 *
417 * ```
418 * this.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
419 * this.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
420 * this.append('Warning', '199 Miscellaneous warning');
421 * ```
422 */
423 append(field: string, val: string | string[]): void;
424
425 /**
426 * Remove header `field`.
427 */
428 remove(field: string): void;
429
430 /**
431 * Checks if the request is writable.
432 * Tests for the existence of the socket
433 * as node sometimes does not set it.
434 */
435 writable: boolean;
436
437 /**
438 * Flush any set headers, and begin the body
439 */
440 flushHeaders(): void;
441}
442
443declare class Application<
444 StateT = Application.DefaultState,
445 ContextT = Application.DefaultContext,
446> extends EventEmitter {
447 proxy: boolean;
448 proxyIpHeader: string;
449 maxIpsCount: number;
450 middleware: Application.Middleware<StateT, ContextT>[];
451 subdomainOffset: number;
452 env: string;
453 context: Application.BaseContext & ContextT;
454 request: Application.BaseRequest;
455 response: Application.BaseResponse;
456 silent: boolean;
457 keys: Keygrip | string[];
458
459 /**
460 * @param {object} [options] Application options
461 * @param {string} [options.env='development'] Environment
462 * @param {string[]} [options.keys] Signed cookie keys
463 * @param {boolean} [options.proxy] Trust proxy headers
464 * @param {number} [options.subdomainOffset] Subdomain offset
465 * @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For
466 * @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity)
467 */
468 constructor(options?: {
469 env?: string | undefined;
470 keys?: string[] | undefined;
471 proxy?: boolean | undefined;
472 subdomainOffset?: number | undefined;
473 proxyIpHeader?: string | undefined;
474 maxIpsCount?: number | undefined;
475 });
476
477 /**
478 * Shorthand for:
479 *
480 * http.createServer(app.callback()).listen(...)
481 */
482 listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): Server;
483 listen(port: number, hostname?: string, listeningListener?: () => void): Server;
484 listen(port: number, backlog?: number, listeningListener?: () => void): Server;
485 listen(port: number, listeningListener?: () => void): Server;
486 listen(path: string, backlog?: number, listeningListener?: () => void): Server;
487 listen(path: string, listeningListener?: () => void): Server;
488 listen(options: ListenOptions, listeningListener?: () => void): Server;
489 listen(handle: any, backlog?: number, listeningListener?: () => void): Server;
490 listen(handle: any, listeningListener?: () => void): Server;
491
492 /**
493 * Return JSON representation.
494 * We only bother showing settings.
495 */
496 inspect(): any;
497
498 /**
499 * Return JSON representation.
500 * We only bother showing settings.
501 */
502 toJSON(): any;
503
504 /**
505 * Use the given middleware `fn`.
506 *
507 * Old-style middleware will be converted.
508 */
509 use<NewStateT = {}, NewContextT = {}>(
510 middleware: Application.Middleware<StateT & NewStateT, ContextT & NewContextT>,
511 ): Application<StateT & NewStateT, ContextT & NewContextT>;
512
513 /**
514 * Return a request handler callback
515 * for node's native http/http2 server.
516 */
517 callback(): (req: IncomingMessage | Http2ServerRequest, res: ServerResponse | Http2ServerResponse) => Promise<void>;
518
519 /**
520 * Initialize a new context.
521 *
522 * @api private
523 */
524 createContext<StateT = Application.DefaultState>(
525 req: IncomingMessage,
526 res: ServerResponse,
527 ): Application.ParameterizedContext<StateT>;
528
529 /**
530 * Default error handler.
531 *
532 * @api private
533 */
534 onerror(err: Error): void;
535}
536
537declare namespace Application {
538 type DefaultStateExtends = any;
539 /**
540 * This interface can be augmented by users to add types to Koa's default state
541 */
542 interface DefaultState extends DefaultStateExtends {}
543
544 type DefaultContextExtends = {};
545 /**
546 * This interface can be augmented by users to add types to Koa's default context
547 */
548 interface DefaultContext extends DefaultContextExtends {
549 /**
550 * Custom properties.
551 */
552 [key: PropertyKey]: any;
553 }
554
555 type Middleware<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = any> = compose.Middleware<
556 ParameterizedContext<StateT, ContextT, ResponseBodyT>
557 >;
558
559 interface BaseRequest extends ContextDelegatedRequest {
560 /**
561 * Get the charset when present or undefined.
562 */
563 charset: string;
564
565 /**
566 * Return parsed Content-Length when present.
567 */
568 length: number;
569
570 /**
571 * Return the request mime type void of
572 * parameters such as "charset".
573 */
574 type: string;
575
576 /**
577 * Inspect implementation.
578 */
579 inspect(): any;
580
581 /**
582 * Return JSON representation.
583 */
584 toJSON(): any;
585 }
586
587 interface BaseResponse extends ContextDelegatedResponse {
588 /**
589 * Return the request socket.
590 *
591 * @return {Connection}
592 * @api public
593 */
594 socket: Socket;
595
596 /**
597 * Return response header.
598 */
599 header: OutgoingHttpHeaders;
600
601 /**
602 * Return response header, alias as response.header
603 */
604 headers: OutgoingHttpHeaders;
605
606 /**
607 * Check whether the response is one of the listed types.
608 * Pretty much the same as `this.request.is()`.
609 *
610 * @param {String|Array} types...
611 * @return {String|false}
612 * @api public
613 */
614 // is(): string;
615 is(...types: string[]): string | false | null;
616 is(types: string[]): string | false | null;
617
618 /**
619 * Return response header. If the header is not set, will return an empty
620 * string.
621 *
622 * The `Referrer` header field is special-cased, both `Referrer` and
623 * `Referer` are interchangeable.
624 *
625 * Examples:
626 *
627 * this.get('Content-Type');
628 * // => "text/plain"
629 *
630 * this.get('content-type');
631 * // => "text/plain"
632 *
633 * this.get('Something');
634 * // => ''
635 */
636 get(field: string): string;
637
638 /**
639 * Inspect implementation.
640 */
641 inspect(): any;
642
643 /**
644 * Return JSON representation.
645 */
646 toJSON(): any;
647 }
648
649 interface BaseContext extends ContextDelegatedRequest, ContextDelegatedResponse {
650 /**
651 * util.inspect() implementation, which
652 * just returns the JSON output.
653 */
654 inspect(): any;
655
656 /**
657 * Return JSON representation.
658 *
659 * Here we explicitly invoke .toJSON() on each
660 * object, as iteration will otherwise fail due
661 * to the getters and cause utilities such as
662 * clone() to fail.
663 */
664 toJSON(): any;
665
666 /**
667 * Similar to .throw(), adds assertion.
668 *
669 * this.assert(this.user, 401, 'Please login!');
670 *
671 * See: https://github.com/jshttp/http-assert
672 */
673 assert: typeof httpAssert;
674
675 /**
676 * Throw an error with `msg` and optional `status`
677 * defaulting to 500. Note that these are user-level
678 * errors, and the message may be exposed to the client.
679 *
680 * this.throw(403)
681 * this.throw('name required', 400)
682 * this.throw(400, 'name required')
683 * this.throw('something exploded')
684 * this.throw(new Error('invalid'), 400);
685 * this.throw(400, new Error('invalid'));
686 *
687 * See: https://github.com/jshttp/http-errors
688 */
689 throw(message: string, code?: number, properties?: {}): never;
690 throw(status: number): never;
691 throw(...properties: Array<number | string | {}>): never;
692
693 /**
694 * Default error handling.
695 */
696 onerror(err: Error): void;
697 }
698
699 interface Request extends BaseRequest {
700 app: Application;
701 req: IncomingMessage;
702 res: ServerResponse;
703 ctx: Context;
704 response: Response;
705 originalUrl: string;
706 ip: string;
707 accept: accepts.Accepts;
708 }
709
710 interface Response extends BaseResponse {
711 app: Application;
712 req: IncomingMessage;
713 res: ServerResponse;
714 ctx: Context;
715 request: Request;
716 }
717
718 interface ExtendableContext extends BaseContext {
719 app: Application;
720 request: Request;
721 response: Response;
722 req: IncomingMessage;
723 res: ServerResponse;
724 originalUrl: string;
725 cookies: Cookies;
726 accept: accepts.Accepts;
727 /**
728 * To bypass Koa's built-in response handling, you may explicitly set `ctx.respond = false;`
729 */
730 respond?: boolean | undefined;
731 }
732
733 type ParameterizedContext<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = unknown> =
734 & ExtendableContext
735 & { state: StateT }
736 & ContextT
737 & { body: ResponseBodyT; response: { body: ResponseBodyT } };
738
739 interface Context extends ParameterizedContext {}
740
741 type Next = () => Promise<any>;
742
743 /**
744 * A re-export of `HttpError` from the `http-error` package.
745 *
746 * This is the error type that is thrown by `ctx.assert()` and `ctx.throw()`.
747 */
748 const HttpError: typeof HttpErrors.HttpError;
749}
750
751export = Application;