diff --git a/koa-hbs/index.d.ts b/koa-hbs/index.d.ts index 51c609e296..f38d2e9fdd 100644 --- a/koa-hbs/index.d.ts +++ b/koa-hbs/index.d.ts @@ -37,7 +37,7 @@ declare namespace Hbs { layoutsPath?: string, contentHelperName?: string, blockHelperName?: string, - disableCache?: boolean + disableCache?: boolean } } @@ -50,7 +50,7 @@ declare const hbs: Hbs; export = hbs; declare module "koa" { - export interface Context extends Request, Response { + export interface Context { render(tpl: string, locals?: {[key: string]: any}): Promise; } } \ No newline at end of file diff --git a/koa-json-error/index.d.ts b/koa-json-error/index.d.ts index 9f02cce994..f1a54470ca 100644 --- a/koa-json-error/index.d.ts +++ b/koa-json-error/index.d.ts @@ -2,6 +2,7 @@ // Project: https://github.com/koajs/json-error // Definitions by: Mudkip // Definitions: https://github.com/mudkipme/DefinitelyTyped +// TypeScript Version: 2.1 import * as Koa from "koa"; diff --git a/koa-passport/index.d.ts b/koa-passport/index.d.ts index 2bdf4bcfac..e3a318004a 100644 --- a/koa-passport/index.d.ts +++ b/koa-passport/index.d.ts @@ -13,7 +13,7 @@ import * as Koa from "koa"; declare module "koa" { - interface Request { + interface Context { authInfo?: any; user?: any; diff --git a/koa-session-minimal/index.d.ts b/koa-session-minimal/index.d.ts index 3fe9da3a52..02d3a68004 100644 --- a/koa-session-minimal/index.d.ts +++ b/koa-session-minimal/index.d.ts @@ -17,7 +17,7 @@ import * as Koa from "koa"; import * as cookies from "cookies"; declare module "koa" { - interface Request { + interface Context { session: any; sessionHandler: { regenerateId: () => void }; } diff --git a/koa/index.d.ts b/koa/index.d.ts index 09b2a64426..99e2c04498 100644 --- a/koa/index.d.ts +++ b/koa/index.d.ts @@ -1,6 +1,6 @@ // Type definitions for Koa 2.x // Project: http://koajs.com -// Definitions by: DavidCai1993 +// Definitions by: DavidCai1993 , jKey Lu // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /* =================== USAGE =================== @@ -14,172 +14,645 @@ =============================================== */ /// -import { EventEmitter } from "events"; -import * as cookies from "cookies"; -import * as http from "http"; -import * as net from "net"; +import { EventEmitter } from 'events'; +import { IncomingMessage, ServerResponse, Server } from 'http'; +import { Socket, ListenOptions } from 'net'; +import * as compose from 'koa-compose'; +import * as Keygrip from 'keygrip'; +import * as httpAssert from 'http-assert'; +import * as Cookies from 'cookies'; +import * as accepts from 'accepts'; + +declare interface ContextDelegatedRequest { + /** + * Return request header. + */ + header: any; + /** + * Return request header, alias as request.header + */ + headers: any; + + /** + * Get/Set request URL. + */ + url: string; + + /** + * Get origin of URL. + */ + origin: string; + + /** + * Get full request URL. + */ + href: string; + + /** + * Get/Set request method. + */ + method: string; + + /** + * Get request pathname. + * Set pathname, retaining the query-string when present. + */ + path: string; + + /** + * Get parsed query-string. + * Set query-string as an object. + */ + query: any; + + /** + * Get/Set query string. + */ + querystring: string; + + /** + * Get the search string. Same as the querystring + * except it includes the leading ?. + * + * Set the search string. Same as + * response.querystring= but included for ubiquity. + */ + search: string; -export = Koa; + /** + * Parse the "Host" header field host + * and support X-Forwarded-Host when a + * proxy is enabled. + */ + host: string; -declare namespace Koa { - export interface Context extends Request, Response { - app: Koa; - req: http.IncomingMessage; - res: http.ServerResponse; - request: Request; - response: Response; + /** + * Parse the "Host" header field hostname + * and support X-Forwarded-Host when a + * proxy is enabled. + */ + hostname: string; - cookies: cookies.ICookies; - originalUrl: string; - state: any; + /** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + */ + fresh: boolean; - name?: string; - respond?: boolean; + /** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + */ + stale: boolean; - assert(test: any, ...args: any[]): void; - onerror(err?: any): void; - throw(...args: any[]): void; + /** + * Check if the request is idempotent. + */ + idempotent: boolean; - toJSON(): any; - inspect(): any; + /** + * Return the request socket. + */ + socket: Socket; - [key: string]: any; - } + /** + * Return the protocol string "http" or "https" + * when requested with TLS. When the proxy setting + * is enabled the "X-Forwarded-Proto" header + * field will be trusted. If you're running behind + * a reverse proxy that supplies https for you this + * may be enabled. + */ + protocol: string; - export interface Request { - app: Koa; - req: http.IncomingMessage; - res: http.ServerResponse; - ctx: Context; - response: Response; + /** + * Short-hand for: + * + * this.protocol == 'https' + */ + secure: boolean; - fresh: boolean; - header: any; - headers: any; - host: string; - hostname: string; - href: string; - idempotent: boolean; - ip: string; - ips: string[]; - method: string; - origin: string; - originalUrl: string; - path: string; - protocol: string; - query: any; - querystring: string; - search: string; - secure: boolean; - socket: net.Socket; - stale: boolean; - subdomains: string[]; - type: string; - url: string; + /** + * When `app.proxy` is `true`, parse + * the "X-Forwarded-For" ip address list. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream. + */ + ips: string[]; - charset?: string; - length?: number; + /** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain + * of the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting `app.subdomainOffset`. + * + * For example, if the domain is "tobi.ferrets.example.com": + * If `app.subdomainOffset` is not set, this.subdomains is + * `["ferrets", "tobi"]`. + * If `app.subdomainOffset` is 3, this.subdomains is `["tobi"]`. + */ + subdomains: string[]; - accepts(): string[]; - accepts(arg: string): void | string; - accepts(arg: string[]): void | string; - accepts(...args: string[]): void | string; - acceptsCharsets(): string[]; - acceptsCharsets(arg: string): void | string; - acceptsCharsets(arg: string[]): void | string; - acceptsCharsets(...args: string[]): void | string; - acceptsEncodings(): string[]; - acceptsEncodings(arg: string): void | string; - acceptsEncodings(arg: string[]): void | string; - acceptsEncodings(...args: string[]): void | string; - acceptsLanguages(): string[]; - acceptsLanguages(arg: string): void | string; - acceptsLanguages(arg: string[]): void | string; - acceptsLanguages(...args: string[]): void | string; - get(field: string): string; - is(): string[]; - is(arg: string): void | string; - is(arg: string[]): void | string; - is(...args: string[]): void | string; + /** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.accepts('html'); + * // => "html" + * this.accepts('text/html'); + * // => "text/html" + * this.accepts('json', 'text'); + * // => "json" + * this.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.accepts('image/png'); + * this.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.accepts(['html', 'json']); + * this.accepts('html', 'json'); + * // => "json" + */ + accepts(): string[] | boolean; + accepts(...types: string[]): string | boolean; + accepts(types: string[]): string | boolean; - toJSON(): any; - inspect(): any; - } + /** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + */ + acceptsEncodings(): string[] | boolean; + acceptsEncodings(...encodings: string[]): string | boolean; + acceptsEncodings(encodings: string[]): string | boolean; - export interface Response { - app: Koa; - req: http.IncomingMessage; - res: http.ServerResponse; - ctx: Context; - request: Request; + /** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + */ + acceptsCharsets(): string[] | boolean; + acceptsCharsets(...charsets: string[]): string | boolean; + acceptsCharsets(charsets: string[]): string | boolean; - body: any; - etag: string; - header: any; - headers: any; - headerSent: boolean; - lastModified: Date; - message: string; - socket: net.Socket; - status: number; - type: string; - writable: boolean; + /** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + */ + acceptsLanguages(): string[] | boolean; + acceptsLanguages(...langs: string[]): string | boolean; + acceptsLanguages(langs: string[]): string | boolean; - charset?: string; - length?: number; + /** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains any of the give mime `type`s. + * If there is no request body, `null` is returned. + * If there is no content type, `false` is returned. + * Otherwise, it returns the first `type` that matches. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * this.is('html'); // => 'html' + * this.is('text/html'); // => 'text/html' + * this.is('text/*', 'application/json'); // => 'text/html' + * + * // When Content-Type is application/json + * this.is('json', 'urlencoded'); // => 'json' + * this.is('application/json'); // => 'application/json' + * this.is('html', 'application/*'); // => 'application/json' + * + * this.is('html'); // => false + */ + // is(): string | boolean; + is(...types: string[]): string | boolean; + is(types: string[]): string | boolean; - append(field: string, val: string | string[]): void; - attachment(filename?: string): void; - get(field: string): string; - is(): string[]; - is(arg: string): void | string; - is(arg: string[]): void | string; - is(...args: string[]): void | string; - redirect(url: string, alt?: string): void; - remove(field: string): void; - set(field: string, val: string | string[]): void; - set(field: any): void; - vary(field: string): void; - - toJSON(): any; - inspect(): any; - } - - export type Middleware = (ctx: Koa.Context, next: () => Promise) => any; + /** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * this.get('Content-Type'); + * // => "text/plain" + * + * this.get('content-type'); + * // => "text/plain" + * + * this.get('Something'); + * // => undefined + */ + get(field: string): string; } -declare class Koa extends EventEmitter { - subdomainOffset: number; - server: http.Server; - env: string; - context: Koa.Context; - keys: string[]; +declare interface BaseRequest extends ContextDelegatedRequest { + /** + * Get the charset when present or undefined. + */ + charset: string; + + /** + * Return parsed Content-Length when present. + */ + length: number; + + /** + * Return the request mime type void of + * parameters such as "charset". + */ + type: string; + + /** + * Inspect implementation. + */ + inspect(): any; + + /** + * Return JSON representation. + */ + toJSON(): any; +} + +declare interface ContextDelegatedResponse { + /** + * Get/Set response status code. + */ + status: number; + + /** + * Get response status message + */ + message: string; + + /** + * Get/Set response body. + */ + body: any; + + /** + * Return parsed response Content-Length when present. + * Set Content-Length field to `n`. + */ + length: number; + + /** + * Check if a header has been written to the socket. + */ + headerSent: boolean; + + /** + * Vary on `field`. + */ + vary(field: string): void; + + /** + * Perform a 302 redirect to `url`. + * + * The string "back" is special-cased + * to provide Referrer support, when Referrer + * is not present `alt` or "/" is used. + * + * Examples: + * + * this.redirect('back'); + * this.redirect('back', '/index.html'); + * this.redirect('/login'); + * this.redirect('http://google.com'); + */ + redirect(url: string, alt?: string): void; + + /** + * Set Content-Disposition header to "attachment" with optional `filename`. + */ + attachment(filename: string): void; + + /** + * Return the response mime type void of + * parameters such as "charset". + * + * Set Content-Type response header with `type` through `mime.lookup()` + * when it does not contain a charset. + * + * Examples: + * + * this.type = '.html'; + * this.type = 'html'; + * this.type = 'json'; + * this.type = 'application/json'; + * this.type = 'png'; + */ + type: string; + + /** + * Get the Last-Modified date in Date form, if it exists. + * Set the Last-Modified date using a string or a Date. + * + * this.response.lastModified = new Date(); + * this.response.lastModified = '2013-09-13'; + */ + lastModified: Date; + + /** + * Get/Set the ETag of a response. + * This will normalize the quotes if necessary. + * + * this.response.etag = 'md5hashsum'; + * this.response.etag = '"md5hashsum"'; + * this.response.etag = 'W/"123456789"'; + * + * @param {String} etag + * @api public + */ + etag: string; + + /** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * this.set('Foo', ['bar', 'baz']); + * this.set('Accept', 'application/json'); + * this.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + */ + set(field: { [key: string]: string; }): void; + set(field: string, val: string | string[]): void; + + /** + * Append additional header `field` with value `val`. + * + * Examples: + * + * ``` + * this.append('Link', ['', '']); + * this.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly'); + * this.append('Warning', '199 Miscellaneous warning'); + * ``` + */ + append(field: string, val: string | string[]): void; + + /** + * Remove header `field`. + */ + remove(field: string): void; + + /** + * Checks if the request is writable. + * Tests for the existence of the socket + * as node sometimes does not set it. + */ + writable: boolean; + + /** + * Flush any set headers, and begin the body + */ + flushHeaders(): void; +} + +declare interface BaseResponse extends ContextDelegatedResponse { + /** + * Return the request socket. + * + * @return {Connection} + * @api public + */ + socket: Socket; + + /** + * Return response header. + */ + header: any; + + /** + * Return response header, alias as response.header + */ + headers: any; + + /** + * Check whether the response is one of the listed types. + * Pretty much the same as `this.request.is()`. + * + * @param {String|Array} types... + * @return {String|false} + * @api public + */ + // is(): string; + is(...types: string[]): string; + is(types: string[]): string; + + /** + * Return response header. + * + * Examples: + * + * this.get('Content-Type'); + * // => "text/plain" + * + * this.get('content-type'); + * // => "text/plain" + */ + get(field: string): string; + + /** + * Inspect implementation. + */ + inspect(): any; + + /** + * Return JSON representation. + */ + toJSON(): any; +} + + +declare interface BaseContext extends ContextDelegatedRequest, ContextDelegatedResponse { + /** + * util.inspect() implementation, which + * just returns the JSON output. + */ + inspect(): any; + + /** + * Return JSON representation. + * + * Here we explicitly invoke .toJSON() on each + * object, as iteration will otherwise fail due + * to the getters and cause utilities such as + * clone() to fail. + */ + toJSON(): any; + + /** + * Similar to .throw(), adds assertion. + * + * this.assert(this.user, 401, 'Please login!'); + * + * See: https://github.com/jshttp/http-assert + */ + assert: typeof httpAssert; + + /** + * Throw an error with `msg` and optional `status` + * defaulting to 500. Note that these are user-level + * errors, and the message may be exposed to the client. + * + * this.throw(403) + * this.throw('name required', 400) + * this.throw(400, 'name required') + * this.throw('something exploded') + * this.throw(new Error('invalid'), 400); + * this.throw(400, new Error('invalid')); + * + * See: https://github.com/jshttp/http-errors + */ + throw(message: string, code?: number, properties?: {}): never; + throw(status: number): never; + throw(...properties: Array): never; + + /** + * Default error handling. + */ + onerror(err: Error): void; +} + +declare class Application extends EventEmitter { proxy: boolean; - request: Koa.Request; - response: Koa.Response; + middleware: Application.Middleware[]; + subdomainOffset: number; + env: string; + context: BaseContext; + request: BaseRequest; + response: BaseResponse; silent: boolean; + keys: Keygrip | string[]; constructor(); - // From node.d.ts - listen(): http.Server; - listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function): http.Server; - listen(port: number, hostname?: string, listeningListener?: Function): http.Server; - listen(port: number, backlog?: number, listeningListener?: Function): http.Server; - listen(port: number, listeningListener?: Function): http.Server; - listen(path: string, backlog?: number, listeningListener?: Function): http.Server; - listen(path: string, listeningListener?: Function): http.Server; - listen(handle: any, backlog?: number, listeningListener?: Function): http.Server; - listen(handle: any, listeningListener?: Function): http.Server; - listen(options: net.ListenOptions, listeningListener?: Function): http.Server; + /** + * Shorthand for: + * + * http.createServer(app.callback()).listen(...) + */ + listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): Server; + listen(port: number, hostname?: string, listeningListener?: () => void): Server; + /* tslint:disable:unified-signatures */ + listen(port: number, backlog?: number, listeningListener?: () => void): Server; + listen(port: number, listeningListener?: () => void): Server; + listen(path: string, backlog?: number, listeningListener?: () => void): Server; + listen(path: string, listeningListener?: () => void): Server; + listen(options: ListenOptions, listeningListener?: () => void): Server; + listen(handle: any, backlog?: number, listeningListener?: () => void): Server; + listen(handle: any, listeningListener?: () => void): Server; + /* tslint:enable:unified-signatures*/ - callback(): (req: http.IncomingMessage, res: http.ServerResponse) => void; - onerror(err: any): void; - use(middleware: Koa.Middleware): Koa; - - toJSON(): any; + /** + * Return JSON representation. + * We only bother showing settings. + */ inspect(): any; - onerror(err: any): void; + + /** + * Return JSON representation. + * We only bother showing settings. + */ + toJSON(): any; + + /** + * Use the given middleware `fn`. + * + * Old-style middleware will be converted. + */ + use(middleware: Application.Middleware): this; + + /** + * Return a request handler callback + * for node's native http server. + */ + callback(): (req: IncomingMessage, res: ServerResponse) => void; + + /** + * Initialize a new context. + * + * @api private + */ + createContext(req: IncomingMessage, res: ServerResponse): Application.Context; + + /** + * Default error handler. + * + * @api private + */ + onerror(err: Error): void; } +declare namespace Application { + type Middleware = compose.Middleware; + + interface Request extends BaseRequest { + app: Application; + req: IncomingMessage; + res: ServerResponse; + ctx: Context; + response: Response; + originalUrl: string; + ip: string; + accept: accepts.Accepts; + } + + interface Response extends BaseResponse { + app: Application; + req: IncomingMessage; + res: ServerResponse; + ctx: Context; + request: Request; + } + + interface Context extends BaseContext { + app: Application; + request: Request; + response: Response; + req: IncomingMessage; + res: ServerResponse; + originalUrl: string; + cookies: Cookies; + accept: accepts.Accepts; + state: any; + } +} + +export = Application;