UNPKG

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