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