UNPKG

21.3 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 { IncomingMessage, ServerResponse, Server, IncomingHttpHeaders, OutgoingHttpHeaders } from 'http';
28import { Http2ServerRequest, Http2ServerResponse } from 'http2';
29import httpAssert = require('http-assert');
30import * as HttpErrors from 'http-errors';
31import * as Keygrip from 'keygrip';
32import * as compose from 'koa-compose';
33import { Socket, ListenOptions } from 'net';
34import * as url from 'url';
35import * as contentDisposition from 'content-disposition';
36import { ParsedUrlQuery } from 'querystring';
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): 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 *
461 * @param {object} [options] Application options
462 * @param {string} [options.env='development'] Environment
463 * @param {string[]} [options.keys] Signed cookie keys
464 * @param {boolean} [options.proxy] Trust proxy headers
465 * @param {number} [options.subdomainOffset] Subdomain offset
466 * @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For
467 * @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity)
468 *
469 */
470 constructor(options?: {
471 env?: string | undefined,
472 keys?: string[] | undefined,
473 proxy?: boolean | undefined,
474 subdomainOffset?: number | undefined,
475 proxyIpHeader?: string | undefined,
476 maxIpsCount?: number | undefined
477 });
478
479 /**
480 * Shorthand for:
481 *
482 * http.createServer(app.callback()).listen(...)
483 */
484 listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): Server;
485 listen(port: number, hostname?: string, listeningListener?: () => void): Server;
486 listen(port: number, backlog?: number, listeningListener?: () => void): Server;
487 listen(port: number, listeningListener?: () => void): Server;
488 listen(path: string, backlog?: number, listeningListener?: () => void): Server;
489 listen(path: string, listeningListener?: () => void): Server;
490 listen(options: ListenOptions, listeningListener?: () => void): Server;
491 listen(handle: any, backlog?: number, listeningListener?: () => void): Server;
492 listen(handle: any, listeningListener?: () => void): Server;
493
494 /**
495 * Return JSON representation.
496 * We only bother showing settings.
497 */
498 inspect(): any;
499
500 /**
501 * Return JSON representation.
502 * We only bother showing settings.
503 */
504 toJSON(): any;
505
506 /**
507 * Use the given middleware `fn`.
508 *
509 * Old-style middleware will be converted.
510 */
511 use<NewStateT = {}, NewContextT = {}>(
512 middleware: Application.Middleware<StateT & NewStateT, ContextT & NewContextT>
513 ): Application<StateT & NewStateT, ContextT & NewContextT>;
514
515 /**
516 * Return a request handler callback
517 * for node's native http/http2 server.
518 */
519 callback(): (req: IncomingMessage | Http2ServerRequest, res: ServerResponse | Http2ServerResponse) => void;
520
521 /**
522 * Initialize a new context.
523 *
524 * @api private
525 */
526 createContext<StateT = Application.DefaultState>(
527 req: IncomingMessage,
528 res: ServerResponse,
529 ): Application.ParameterizedContext<StateT>;
530
531 /**
532 * Default error handler.
533 *
534 * @api private
535 */
536 onerror(err: Error): void;
537}
538
539declare namespace Application {
540 type DefaultStateExtends = any;
541 /**
542 * This interface can be augmented by users to add types to Koa's default state
543 */
544 interface DefaultState extends DefaultStateExtends {}
545
546 type DefaultContextExtends = {};
547 /**
548 * This interface can be augmented by users to add types to Koa's default context
549 */
550 interface DefaultContext extends DefaultContextExtends {
551 /**
552 * Custom properties.
553 */
554 [key: string]: any;
555 }
556
557 type Middleware<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = any> = compose.Middleware<
558 ParameterizedContext<StateT, ContextT, ResponseBodyT>
559 >;
560
561 interface BaseRequest extends ContextDelegatedRequest {
562 /**
563 * Get the charset when present or undefined.
564 */
565 charset: string;
566
567 /**
568 * Return parsed Content-Length when present.
569 */
570 length: number;
571
572 /**
573 * Return the request mime type void of
574 * parameters such as "charset".
575 */
576 type: string;
577
578 /**
579 * Inspect implementation.
580 */
581 inspect(): any;
582
583 /**
584 * Return JSON representation.
585 */
586 toJSON(): any;
587 }
588
589 interface BaseResponse extends ContextDelegatedResponse {
590 /**
591 * Return the request socket.
592 *
593 * @return {Connection}
594 * @api public
595 */
596 socket: Socket;
597
598 /**
599 * Return response header.
600 */
601 header: OutgoingHttpHeaders;
602
603 /**
604 * Return response header, alias as response.header
605 */
606 headers: OutgoingHttpHeaders;
607
608 /**
609 * Check whether the response is one of the listed types.
610 * Pretty much the same as `this.request.is()`.
611 *
612 * @param {String|Array} types...
613 * @return {String|false}
614 * @api public
615 */
616 // is(): string;
617 is(...types: string[]): string | false | null;
618 is(types: string[]): string | false | null;
619
620 /**
621 * Return response header. If the header is not set, will return an empty
622 * string.
623 *
624 * The `Referrer` header field is special-cased, both `Referrer` and
625 * `Referer` are interchangeable.
626 *
627 * Examples:
628 *
629 * this.get('Content-Type');
630 * // => "text/plain"
631 *
632 * this.get('content-type');
633 * // => "text/plain"
634 *
635 * this.get('Something');
636 * // => ''
637 */
638 get(field: string): string;
639
640 /**
641 * Inspect implementation.
642 */
643 inspect(): any;
644
645 /**
646 * Return JSON representation.
647 */
648 toJSON(): any;
649 }
650
651 interface BaseContext extends ContextDelegatedRequest, ContextDelegatedResponse {
652 /**
653 * util.inspect() implementation, which
654 * just returns the JSON output.
655 */
656 inspect(): any;
657
658 /**
659 * Return JSON representation.
660 *
661 * Here we explicitly invoke .toJSON() on each
662 * object, as iteration will otherwise fail due
663 * to the getters and cause utilities such as
664 * clone() to fail.
665 */
666 toJSON(): any;
667
668 /**
669 * Similar to .throw(), adds assertion.
670 *
671 * this.assert(this.user, 401, 'Please login!');
672 *
673 * See: https://github.com/jshttp/http-assert
674 */
675 assert: typeof httpAssert;
676
677 /**
678 * Throw an error with `msg` and optional `status`
679 * defaulting to 500. Note that these are user-level
680 * errors, and the message may be exposed to the client.
681 *
682 * this.throw(403)
683 * this.throw('name required', 400)
684 * this.throw(400, 'name required')
685 * this.throw('something exploded')
686 * this.throw(new Error('invalid'), 400);
687 * this.throw(400, new Error('invalid'));
688 *
689 * See: https://github.com/jshttp/http-errors
690 */
691 throw(message: string, code?: number, properties?: {}): never;
692 throw(status: number): never;
693 throw(...properties: Array<number | string | {}>): never;
694
695 /**
696 * Default error handling.
697 */
698 onerror(err: Error): void;
699 }
700
701 interface Request extends BaseRequest {
702 app: Application;
703 req: IncomingMessage;
704 res: ServerResponse;
705 ctx: Context;
706 response: Response;
707 originalUrl: string;
708 ip: string;
709 accept: accepts.Accepts;
710 }
711
712 interface Response extends BaseResponse {
713 app: Application;
714 req: IncomingMessage;
715 res: ServerResponse;
716 ctx: Context;
717 request: Request;
718 }
719
720 interface ExtendableContext extends BaseContext {
721 app: Application;
722 request: Request;
723 response: Response;
724 req: IncomingMessage;
725 res: ServerResponse;
726 originalUrl: string;
727 cookies: Cookies;
728 accept: accepts.Accepts;
729 /**
730 * To bypass Koa's built-in response handling, you may explicitly set `ctx.respond = false;`
731 */
732 respond?: boolean | undefined;
733 }
734
735 type ParameterizedContext<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = unknown> = ExtendableContext
736 & { state: StateT; }
737 & ContextT
738 & { body: ResponseBodyT; response: { body: ResponseBodyT }; };
739
740 interface Context extends ParameterizedContext {}
741
742 type Next = () => Promise<any>;
743
744 /**
745 * A re-export of `HttpError` from the `http-error` package.
746 *
747 * This is the error type that is thrown by `ctx.assert()` and `ctx.throw()`.
748 */
749 const HttpError: typeof HttpErrors.HttpError;
750}
751
752export = Application;