From e618ab91df58fdeda5295ccf987d4cab6c5d8f8f Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Thu, 31 Aug 2017 21:45:18 +0300 Subject: [PATCH 01/10] Updating needle version and authors --- types/needle/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index 8cc61f2a2f..caea4b1a36 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -1,6 +1,6 @@ -// Type definitions for needle 1.4 +// Type definitions for needle 2.0 // Project: https://github.com/tomas/needle -// Definitions by: San Chen , Niklas Mollenhauer +// Definitions by: San Chen , Niklas Mollenhauer , Matanel Sindilevich // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// From dc50040b3fce12be1b2f4068b0d3ed50504fd0fa Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Thu, 31 Aug 2017 22:34:54 +0300 Subject: [PATCH 02/10] Adding documentation --- types/needle/index.d.ts | 164 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 2 deletions(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index caea4b1a36..95fe47a5cf 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -27,58 +27,165 @@ declare module "needle" { type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; interface RequestOptions { + /** + * Returns error if connection takes longer than X milisecs to establish. + * Defaults to 10000 (10 secs). 0 means no timeout. + */ open_timeout?: number; - read_timeout?: number; /** * Alias for open_timeout */ timeout?: number; + /** + * Returns error if data transfer takes longer than X milisecs, + * after connection is established. Defaults to 0 (no timeout). + */ + read_timeout?: number; + /** + * Number of redirects to follow. Defaults to 0. + */ follow_max?: number; /** * Alias for follow_max */ follow?: number; + /** + * Enables multipart/form-data encoding. Defaults to false. + * Use it when uploading files. + */ multipart?: boolean; + /** + * Uses an http.Agent of your choice, instead of the global, default one. + * Useful for tweaking the behaviour at the connection level, such as when doing tunneling. + */ agent?: http.Agent | boolean; + /** + * Forwards request through HTTP(s) proxy. + * Eg. proxy: 'http://user:pass@proxy.server.com:3128'. + * For more advanced proxying/tunneling use a custom agent. + */ proxy?: string; + /** + * Object containing custom HTTP headers for request. + */ headers?: {}; + /** + * Determines what to do with provided username/password. + * Options are auto, digest or basic (default). + * auto will detect the type of authentication depending on the response headers. + */ auth?: "auto" | "digest" | "basic"; + /** + * When true, sets content type to application/json and sends request body as JSON string, + * instead of a query string. + */ json?: boolean; // These properties are overwritten by those in the 'headers' field + /** + * Builds and sets a Cookie header from a { key: 'value' } object. + */ cookies?: Cookies; + /** + * If true, sets 'Accept-Encoding' header to 'gzip,deflate', + * and inflates content if zipped. + * Defaults to false. + */ compressed?: boolean; // Overwritten if present in the URI + /** + * For HTTP basic auth. + */ username?: string; + /** + * For HTTP basic auth. Requires username to be passed, but is optional. + */ password?: string; + /** + * Sets 'Accept' HTTP header. Defaults to */*. + */ accept?: string; + /** + * Sets 'Connection' HTTP header. + * Not set by default, unless running Node < 0.11.4 + * in which case it defaults to close. + */ connection?: string; + /** + * Sets the 'User-Agent' HTTP header. + * Defaults to Needle/{version} (Node.js {node_version}). + */ user_agent?: string; } interface ResponseOptions { + /** + * Whether to decode the text responses to UTF-8, + * if Content-Type header shows a different charset. Defaults to true. + */ decode_response?: boolean; /** * Alias for decode_response */ decode?: boolean; + + /** + * Whether to parse XML or JSON response bodies automagically. + * Defaults to true. + * You can also set this to 'xml' or 'json' in which case Needle + * will only parse the response if the content type matches. + */ parse_response?: boolean; /** * Alias for parse_response */ parse?: boolean; + /** + * Whether to parse response’s Set-Cookie header. + * Defaults to true. + * If parsed, response cookies will be available at resp.cookies. + */ parse_cookies?: boolean; + /** + * Dump response output to file. + * This occurs after parsing and charset decoding is done. + */ output?: string; } interface RedirectOptions { + /** + * Sends the cookies received in the set-cookie header + * as part of the following request. + * false by default. + */ follow_set_cookie?: boolean; + /** + * Sets the 'Referer' header to the requested URI + * when following a redirect. + * false by default. + */ follow_set_referer?: boolean; + /** + * If enabled, resends the request using the original verb + * instead of being rewritten to get with no data. + * false by default. + */ follow_keep_method?: boolean; + /** + * When true, Needle will only follow redirects that point to the same host + * as the original request. + * false by default. + */ follow_if_same_host?: boolean; + /** + * When true, Needle will only follow redirects that point to the same protocol + * as the original request. + * false by default. + */ follow_if_same_protocol?: boolean; } @@ -89,30 +196,83 @@ declare module "needle" { type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; interface NeedleStatic { + /** + * Lets override the defaults for all future requests. + */ defaults(options: NeedleOptions): void; + /** + * Issues an HTTP HEAD request. + */ head(url: string, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP HEAD request. + */ head(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP GET request. + */ get(url: string, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP GET request. + */ get(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP POST request. + */ post(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP POST request. + */ post(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP PUT request. + */ put(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP PUT request. + */ put(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Same behaviour as PUT. + */ patch(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Same behaviour as PUT. + */ patch(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP DELETE request. + */ delete(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP DELETE request. + */ delete(url: string, data: BodyData, options?: NeedleOptions, callback ?: NeedleCallback): ReadableStream; + /** + * Generic request. + * This not only allows for flexibility, but also lets you perform a GET request with data, + * in which case will be appended to the request as a query string, + * unless you pass a json: true option. + * @param method Designates an HTTP verb for the request. + */ request(method: string, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Generic request. + * This not only allows for flexibility, but also lets you perform a GET request with data, + * in which case will be appended to the request as a query string, + * unless you pass a json: true option. + * @param method Designates an HTTP verb for the request. + */ request(method: string, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; } } const needle: Needle.NeedleStatic; export = needle; -} +} \ No newline at end of file From 3c859b02bf5f064cd0f03e59ae3f7c6e5ca238b9 Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Thu, 31 Aug 2017 22:49:29 +0300 Subject: [PATCH 03/10] Adding new RequestOptions --- types/needle/index.d.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index 95fe47a5cf..0d686ea7d7 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -82,6 +82,16 @@ declare module "needle" { * instead of a query string. */ json?: boolean; + /** + * When sending streams, this lets manually set the Content-Length header + * --if the stream's bytecount is known beforehand--, + * preventing ECONNRESET (socket hang up) errors on some servers that misbehave + * when receiving payloads of unknown size. + * Set it to 0 and Needle will get and set the stream's length, + * or leave unset for the default behavior, + * which is no Content-Length header for stream payloads. + */ + stream_length?: number; // These properties are overwritten by those in the 'headers' field /** @@ -118,6 +128,15 @@ declare module "needle" { * Defaults to Needle/{version} (Node.js {node_version}). */ user_agent?: string; + /** + * Sets the 'Content-Type' header. + * Unset by default, unless you're sending data + * in which case it's set accordingly to whatever is being sent + * (application/x-www-form-urlencoded, application/json or multipart/form-data). + * That is, of course, unless the option is passed, + * either here or through options.headers. + */ + content_type?: string; } interface ResponseOptions { From fc184d4a018a9512e7fae4848711e9b9a66353b8 Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Thu, 31 Aug 2017 23:07:57 +0300 Subject: [PATCH 04/10] Adding return type to needle.defaults() --- types/needle/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index 0d686ea7d7..782b479581 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -218,7 +218,7 @@ declare module "needle" { /** * Lets override the defaults for all future requests. */ - defaults(options: NeedleOptions): void; + defaults(options: NeedleOptions): NeedleOptions; /** * Issues an HTTP HEAD request. From ace093aef3ae61d1e4325009f627ba1e163ac4ab Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Fri, 1 Sep 2017 08:31:30 +0300 Subject: [PATCH 05/10] Modernizing .d.ts syntax --- types/needle/index.d.ts | 535 ++++++++++++++++++++-------------------- 1 file changed, 267 insertions(+), 268 deletions(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index 782b479581..a509a07ca0 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -5,293 +5,292 @@ /// -declare module "needle" { - import * as http from 'http'; - import * as Buffer from 'buffer'; - import * as https from 'https'; - namespace Needle { - interface NeedleResponse extends http.IncomingMessage { - body: any; - raw: Buffer; - bytes: number; - } +import * as http from 'http'; +import * as Buffer from 'buffer'; +import * as https from 'https'; - type ReadableStream = NodeJS.ReadableStream; +interface NeedleResponse extends http.IncomingMessage { + body: any; + raw: Buffer; + bytes: number; +} - type NeedleCallback = (error: Error, response: NeedleResponse, body: any) => void; +type ReadableStream = NodeJS.ReadableStream; - interface Cookies { - [name: string]: any; - } +type NeedleCallback = (error: Error, response: NeedleResponse, body: any) => void; - type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; +interface Cookies { + [name: string]: any; +} - interface RequestOptions { - /** - * Returns error if connection takes longer than X milisecs to establish. - * Defaults to 10000 (10 secs). 0 means no timeout. - */ - open_timeout?: number; - /** - * Alias for open_timeout - */ - timeout?: number; +type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; - /** - * Returns error if data transfer takes longer than X milisecs, - * after connection is established. Defaults to 0 (no timeout). - */ - read_timeout?: number; - /** - * Number of redirects to follow. Defaults to 0. - */ - follow_max?: number; - /** - * Alias for follow_max - */ - follow?: number; +interface RequestOptions { + /** + * Returns error if connection takes longer than X milisecs to establish. + * Defaults to 10000 (10 secs). 0 means no timeout. + */ + open_timeout?: number; + /** + * Alias for open_timeout + */ + timeout?: number; - /** - * Enables multipart/form-data encoding. Defaults to false. - * Use it when uploading files. - */ - multipart?: boolean; - /** - * Uses an http.Agent of your choice, instead of the global, default one. - * Useful for tweaking the behaviour at the connection level, such as when doing tunneling. - */ - agent?: http.Agent | boolean; - /** - * Forwards request through HTTP(s) proxy. - * Eg. proxy: 'http://user:pass@proxy.server.com:3128'. - * For more advanced proxying/tunneling use a custom agent. - */ - proxy?: string; - /** - * Object containing custom HTTP headers for request. - */ - headers?: {}; - /** - * Determines what to do with provided username/password. - * Options are auto, digest or basic (default). - * auto will detect the type of authentication depending on the response headers. - */ - auth?: "auto" | "digest" | "basic"; - /** - * When true, sets content type to application/json and sends request body as JSON string, - * instead of a query string. - */ - json?: boolean; - /** - * When sending streams, this lets manually set the Content-Length header - * --if the stream's bytecount is known beforehand--, - * preventing ECONNRESET (socket hang up) errors on some servers that misbehave - * when receiving payloads of unknown size. - * Set it to 0 and Needle will get and set the stream's length, - * or leave unset for the default behavior, - * which is no Content-Length header for stream payloads. - */ - stream_length?: number; + /** + * Returns error if data transfer takes longer than X milisecs, + * after connection is established. Defaults to 0 (no timeout). + */ + read_timeout?: number; + /** + * Number of redirects to follow. Defaults to 0. + */ + follow_max?: number; + /** + * Alias for follow_max + */ + follow?: number; - // These properties are overwritten by those in the 'headers' field - /** - * Builds and sets a Cookie header from a { key: 'value' } object. - */ - cookies?: Cookies; - /** - * If true, sets 'Accept-Encoding' header to 'gzip,deflate', - * and inflates content if zipped. - * Defaults to false. - */ - compressed?: boolean; - // Overwritten if present in the URI - /** - * For HTTP basic auth. - */ - username?: string; - /** - * For HTTP basic auth. Requires username to be passed, but is optional. - */ - password?: string; - /** - * Sets 'Accept' HTTP header. Defaults to */*. - */ - accept?: string; - /** - * Sets 'Connection' HTTP header. - * Not set by default, unless running Node < 0.11.4 - * in which case it defaults to close. - */ - connection?: string; - /** - * Sets the 'User-Agent' HTTP header. - * Defaults to Needle/{version} (Node.js {node_version}). - */ - user_agent?: string; - /** - * Sets the 'Content-Type' header. - * Unset by default, unless you're sending data - * in which case it's set accordingly to whatever is being sent - * (application/x-www-form-urlencoded, application/json or multipart/form-data). - * That is, of course, unless the option is passed, - * either here or through options.headers. - */ - content_type?: string; - } + /** + * Enables multipart/form-data encoding. Defaults to false. + * Use it when uploading files. + */ + multipart?: boolean; + /** + * Uses an http.Agent of your choice, instead of the global, default one. + * Useful for tweaking the behaviour at the connection level, such as when doing tunneling. + */ + agent?: http.Agent | boolean; + /** + * Forwards request through HTTP(s) proxy. + * Eg. proxy: 'http://user:pass@proxy.server.com:3128'. + * For more advanced proxying/tunneling use a custom agent. + */ + proxy?: string; + /** + * Object containing custom HTTP headers for request. + */ + headers?: {}; + /** + * Determines what to do with provided username/password. + * Options are auto, digest or basic (default). + * auto will detect the type of authentication depending on the response headers. + */ + auth?: "auto" | "digest" | "basic"; + /** + * When true, sets content type to application/json and sends request body as JSON string, + * instead of a query string. + */ + json?: boolean; + /** + * When sending streams, this lets manually set the Content-Length header + * --if the stream's bytecount is known beforehand--, + * preventing ECONNRESET (socket hang up) errors on some servers that misbehave + * when receiving payloads of unknown size. + * Set it to 0 and Needle will get and set the stream's length, + * or leave unset for the default behavior, + * which is no Content-Length header for stream payloads. + */ + stream_length?: number; - interface ResponseOptions { - /** - * Whether to decode the text responses to UTF-8, - * if Content-Type header shows a different charset. Defaults to true. - */ - decode_response?: boolean; - /** - * Alias for decode_response - */ - decode?: boolean; + // These properties are overwritten by those in the 'headers' field + /** + * Builds and sets a Cookie header from a { key: 'value' } object. + */ + cookies?: Cookies; + /** + * If true, sets 'Accept-Encoding' header to 'gzip,deflate', + * and inflates content if zipped. + * Defaults to false. + */ + compressed?: boolean; + // Overwritten if present in the URI + /** + * For HTTP basic auth. + */ + username?: string; + /** + * For HTTP basic auth. Requires username to be passed, but is optional. + */ + password?: string; + /** + * Sets 'Accept' HTTP header. Defaults to */*. + */ + accept?: string; + /** + * Sets 'Connection' HTTP header. + * Not set by default, unless running Node < 0.11.4 + * in which case it defaults to close. + */ + connection?: string; + /** + * Sets the 'User-Agent' HTTP header. + * Defaults to Needle/{version} (Node.js {node_version}). + */ + user_agent?: string; + /** + * Sets the 'Content-Type' header. + * Unset by default, unless you're sending data + * in which case it's set accordingly to whatever is being sent + * (application/x-www-form-urlencoded, application/json or multipart/form-data). + * That is, of course, unless the option is passed, + * either here or through options.headers. + */ + content_type?: string; +} - /** - * Whether to parse XML or JSON response bodies automagically. - * Defaults to true. - * You can also set this to 'xml' or 'json' in which case Needle - * will only parse the response if the content type matches. - */ - parse_response?: boolean; - /** - * Alias for parse_response - */ - parse?: boolean; +interface ResponseOptions { + /** + * Whether to decode the text responses to UTF-8, + * if Content-Type header shows a different charset. Defaults to true. + */ + decode_response?: boolean; + /** + * Alias for decode_response + */ + decode?: boolean; - /** - * Whether to parse response’s Set-Cookie header. - * Defaults to true. - * If parsed, response cookies will be available at resp.cookies. - */ - parse_cookies?: boolean; - /** - * Dump response output to file. - * This occurs after parsing and charset decoding is done. - */ - output?: string; - } + /** + * Whether to parse XML or JSON response bodies automagically. + * Defaults to true. + * You can also set this to 'xml' or 'json' in which case Needle + * will only parse the response if the content type matches. + */ + parse_response?: boolean; + /** + * Alias for parse_response + */ + parse?: boolean; - interface RedirectOptions { - /** - * Sends the cookies received in the set-cookie header - * as part of the following request. - * false by default. - */ - follow_set_cookie?: boolean; - /** - * Sets the 'Referer' header to the requested URI - * when following a redirect. - * false by default. - */ - follow_set_referer?: boolean; - /** - * If enabled, resends the request using the original verb - * instead of being rewritten to get with no data. - * false by default. - */ - follow_keep_method?: boolean; - /** - * When true, Needle will only follow redirects that point to the same host - * as the original request. - * false by default. - */ - follow_if_same_host?: boolean; - /** - * When true, Needle will only follow redirects that point to the same protocol - * as the original request. - * false by default. - */ - follow_if_same_protocol?: boolean; - } + /** + * Whether to parse response’s Set-Cookie header. + * Defaults to true. + * If parsed, response cookies will be available at resp.cookies. + */ + parse_cookies?: boolean; + /** + * Dump response output to file. + * This occurs after parsing and charset decoding is done. + */ + output?: string; +} - interface KeyValue { - [key: string]: any; - } +interface RedirectOptions { + /** + * Sends the cookies received in the set-cookie header + * as part of the following request. + * false by default. + */ + follow_set_cookie?: boolean; + /** + * Sets the 'Referer' header to the requested URI + * when following a redirect. + * false by default. + */ + follow_set_referer?: boolean; + /** + * If enabled, resends the request using the original verb + * instead of being rewritten to get with no data. + * false by default. + */ + follow_keep_method?: boolean; + /** + * When true, Needle will only follow redirects that point to the same host + * as the original request. + * false by default. + */ + follow_if_same_host?: boolean; + /** + * When true, Needle will only follow redirects that point to the same protocol + * as the original request. + * false by default. + */ + follow_if_same_protocol?: boolean; +} - type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; +interface KeyValue { + [key: string]: any; +} - interface NeedleStatic { - /** - * Lets override the defaults for all future requests. - */ - defaults(options: NeedleOptions): NeedleOptions; +type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; - /** - * Issues an HTTP HEAD request. - */ - head(url: string, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP HEAD request. - */ - head(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; +declare namespace needle { + /** + * Lets override the defaults for all future requests. + */ + export function defaults(options: NeedleOptions): NeedleOptions; - /** - * Issues an HTTP GET request. - */ - get(url: string, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP GET request. - */ - get(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP HEAD request. + */ + export function head(url: string, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP HEAD request. + */ + export function head(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP POST request. - */ - post(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP POST request. - */ - post(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP GET request. + */ + export function get(url: string, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP GET request. + */ + export function get(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP PUT request. - */ - put(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP PUT request. - */ - put(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP POST request. + */ + export function post(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP POST request. + */ + export function post(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - /** - * Same behaviour as PUT. - */ - patch(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; - /** - * Same behaviour as PUT. - */ - patch(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP PUT request. + */ + export function put(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP PUT request. + */ + export function put(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP DELETE request. - */ - delete(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; - /** - * Issues an HTTP DELETE request. - */ - delete(url: string, data: BodyData, options?: NeedleOptions, callback ?: NeedleCallback): ReadableStream; + /** + * Same behaviour as PUT. + */ + export function patch(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Same behaviour as PUT. + */ + export function patch(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - /** - * Generic request. - * This not only allows for flexibility, but also lets you perform a GET request with data, - * in which case will be appended to the request as a query string, - * unless you pass a json: true option. - * @param method Designates an HTTP verb for the request. - */ - request(method: string, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; - /** - * Generic request. - * This not only allows for flexibility, but also lets you perform a GET request with data, - * in which case will be appended to the request as a query string, - * unless you pass a json: true option. - * @param method Designates an HTTP verb for the request. - */ - request(method: string, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; - } - } - const needle: Needle.NeedleStatic; - export = needle; -} \ No newline at end of file + /** + * Issues an HTTP DELETE request. + */ + function deleteFunc(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Issues an HTTP DELETE request. + */ + function deleteFunc(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + // See https://github.com/Microsoft/TypeScript/issues/1784#issuecomment-258720219 + export { deleteFunc as delete }; + + /** + * Generic request. + * This not only allows for flexibility, but also lets you perform a GET request with data, + * in which case will be appended to the request as a query string, + * unless you pass a json: true option. + * @param method Designates an HTTP verb for the request. + */ + export function request(method: string, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + /** + * Generic request. + * This not only allows for flexibility, but also lets you perform a GET request with data, + * in which case will be appended to the request as a query string, + * unless you pass a json: true option. + * @param method Designates an HTTP verb for the request. + */ + export function request(method: string, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; +} + +export = needle; \ No newline at end of file From 92db09a1c0d126d978de539526d743e69217154e Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Fri, 1 Sep 2017 13:40:58 +0300 Subject: [PATCH 06/10] Adding definitions for calling needle(): Promise directly --- types/needle/index.d.ts | 436 +++++++++++++++++++---------------- types/needle/needle-tests.ts | 175 +++++++++++--- 2 files changed, 379 insertions(+), 232 deletions(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index a509a07ca0..097cc8ba08 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -9,211 +9,241 @@ import * as http from 'http'; import * as Buffer from 'buffer'; import * as https from 'https'; -interface NeedleResponse extends http.IncomingMessage { - body: any; - raw: Buffer; - bytes: number; +declare namespace core { + interface NeedleResponse extends http.IncomingMessage { + body: any; + raw: Buffer; + bytes: number; + } + + type ReadableStream = NodeJS.ReadableStream; + + type NeedleCallback = (error: Error, response: NeedleResponse, body: any) => void; + + interface Cookies { + [name: string]: any; + } + + type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; + + type NeedleReadonlyHttpVerbs = 'get' | 'head'; + + type NeedleReadWriteHttpVerbs = 'delete' | 'patch' | 'post' | 'put'; + + type NeedleHttpVerbs = NeedleReadonlyHttpVerbs | NeedleReadWriteHttpVerbs; + + interface RequestOptions { + /** + * Returns error if connection takes longer than X milisecs to establish. + * Defaults to 10000 (10 secs). 0 means no timeout. + */ + open_timeout?: number; + /** + * Alias for open_timeout + */ + timeout?: number; + + /** + * Returns error if data transfer takes longer than X milisecs, + * after connection is established. Defaults to 0 (no timeout). + */ + read_timeout?: number; + /** + * Number of redirects to follow. Defaults to 0. + */ + follow_max?: number; + /** + * Alias for follow_max + */ + follow?: number; + + /** + * Enables multipart/form-data encoding. Defaults to false. + * Use it when uploading files. + */ + multipart?: boolean; + /** + * Uses an http.Agent of your choice, instead of the global, default one. + * Useful for tweaking the behaviour at the connection level, such as when doing tunneling. + */ + agent?: http.Agent | boolean; + /** + * Forwards request through HTTP(s) proxy. + * Eg. proxy: 'http://user:pass@proxy.server.com:3128'. + * For more advanced proxying/tunneling use a custom agent. + */ + proxy?: string; + /** + * Object containing custom HTTP headers for request. + */ + headers?: {}; + /** + * Determines what to do with provided username/password. + * Options are auto, digest or basic (default). + * auto will detect the type of authentication depending on the response headers. + */ + auth?: "auto" | "digest" | "basic"; + /** + * When true, sets content type to application/json and sends request body as JSON string, + * instead of a query string. + */ + json?: boolean; + /** + * When sending streams, this lets manually set the Content-Length header + * --if the stream's bytecount is known beforehand--, + * preventing ECONNRESET (socket hang up) errors on some servers that misbehave + * when receiving payloads of unknown size. + * Set it to 0 and Needle will get and set the stream's length, + * or leave unset for the default behavior, + * which is no Content-Length header for stream payloads. + */ + stream_length?: number; + + // These properties are overwritten by those in the 'headers' field + /** + * Builds and sets a Cookie header from a { key: 'value' } object. + */ + cookies?: Cookies; + /** + * If true, sets 'Accept-Encoding' header to 'gzip,deflate', + * and inflates content if zipped. + * Defaults to false. + */ + compressed?: boolean; + // Overwritten if present in the URI + /** + * For HTTP basic auth. + */ + username?: string; + /** + * For HTTP basic auth. Requires username to be passed, but is optional. + */ + password?: string; + /** + * Sets 'Accept' HTTP header. Defaults to */*. + */ + accept?: string; + /** + * Sets 'Connection' HTTP header. + * Not set by default, unless running Node < 0.11.4 + * in which case it defaults to close. + */ + connection?: string; + /** + * Sets the 'User-Agent' HTTP header. + * Defaults to Needle/{version} (Node.js {node_version}). + */ + user_agent?: string; + /** + * Sets the 'Content-Type' header. + * Unset by default, unless you're sending data + * in which case it's set accordingly to whatever is being sent + * (application/x-www-form-urlencoded, application/json or multipart/form-data). + * That is, of course, unless the option is passed, + * either here or through options.headers. + */ + content_type?: string; + } + + interface ResponseOptions { + /** + * Whether to decode the text responses to UTF-8, + * if Content-Type header shows a different charset. Defaults to true. + */ + decode_response?: boolean; + /** + * Alias for decode_response + */ + decode?: boolean; + + /** + * Whether to parse XML or JSON response bodies automagically. + * Defaults to true. + * You can also set this to 'xml' or 'json' in which case Needle + * will only parse the response if the content type matches. + */ + parse_response?: boolean; + /** + * Alias for parse_response + */ + parse?: boolean; + + /** + * Whether to parse response’s Set-Cookie header. + * Defaults to true. + * If parsed, response cookies will be available at resp.cookies. + */ + parse_cookies?: boolean; + /** + * Dump response output to file. + * This occurs after parsing and charset decoding is done. + */ + output?: string; + } + + interface RedirectOptions { + /** + * Sends the cookies received in the set-cookie header + * as part of the following request. + * false by default. + */ + follow_set_cookie?: boolean; + /** + * Sets the 'Referer' header to the requested URI + * when following a redirect. + * false by default. + */ + follow_set_referer?: boolean; + /** + * If enabled, resends the request using the original verb + * instead of being rewritten to get with no data. + * false by default. + */ + follow_keep_method?: boolean; + /** + * When true, Needle will only follow redirects that point to the same host + * as the original request. + * false by default. + */ + follow_if_same_host?: boolean; + /** + * When true, Needle will only follow redirects that point to the same protocol + * as the original request. + * false by default. + */ + follow_if_same_protocol?: boolean; + } + + interface KeyValue { + [key: string]: any; + } + + type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; } -type ReadableStream = NodeJS.ReadableStream; - -type NeedleCallback = (error: Error, response: NeedleResponse, body: any) => void; - -interface Cookies { - [name: string]: any; -} - -type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; - -interface RequestOptions { - /** - * Returns error if connection takes longer than X milisecs to establish. - * Defaults to 10000 (10 secs). 0 means no timeout. - */ - open_timeout?: number; - /** - * Alias for open_timeout - */ - timeout?: number; - - /** - * Returns error if data transfer takes longer than X milisecs, - * after connection is established. Defaults to 0 (no timeout). - */ - read_timeout?: number; - /** - * Number of redirects to follow. Defaults to 0. - */ - follow_max?: number; - /** - * Alias for follow_max - */ - follow?: number; - - /** - * Enables multipart/form-data encoding. Defaults to false. - * Use it when uploading files. - */ - multipart?: boolean; - /** - * Uses an http.Agent of your choice, instead of the global, default one. - * Useful for tweaking the behaviour at the connection level, such as when doing tunneling. - */ - agent?: http.Agent | boolean; - /** - * Forwards request through HTTP(s) proxy. - * Eg. proxy: 'http://user:pass@proxy.server.com:3128'. - * For more advanced proxying/tunneling use a custom agent. - */ - proxy?: string; - /** - * Object containing custom HTTP headers for request. - */ - headers?: {}; - /** - * Determines what to do with provided username/password. - * Options are auto, digest or basic (default). - * auto will detect the type of authentication depending on the response headers. - */ - auth?: "auto" | "digest" | "basic"; - /** - * When true, sets content type to application/json and sends request body as JSON string, - * instead of a query string. - */ - json?: boolean; - /** - * When sending streams, this lets manually set the Content-Length header - * --if the stream's bytecount is known beforehand--, - * preventing ECONNRESET (socket hang up) errors on some servers that misbehave - * when receiving payloads of unknown size. - * Set it to 0 and Needle will get and set the stream's length, - * or leave unset for the default behavior, - * which is no Content-Length header for stream payloads. - */ - stream_length?: number; - - // These properties are overwritten by those in the 'headers' field - /** - * Builds and sets a Cookie header from a { key: 'value' } object. - */ - cookies?: Cookies; - /** - * If true, sets 'Accept-Encoding' header to 'gzip,deflate', - * and inflates content if zipped. - * Defaults to false. - */ - compressed?: boolean; - // Overwritten if present in the URI - /** - * For HTTP basic auth. - */ - username?: string; - /** - * For HTTP basic auth. Requires username to be passed, but is optional. - */ - password?: string; - /** - * Sets 'Accept' HTTP header. Defaults to */*. - */ - accept?: string; - /** - * Sets 'Connection' HTTP header. - * Not set by default, unless running Node < 0.11.4 - * in which case it defaults to close. - */ - connection?: string; - /** - * Sets the 'User-Agent' HTTP header. - * Defaults to Needle/{version} (Node.js {node_version}). - */ - user_agent?: string; - /** - * Sets the 'Content-Type' header. - * Unset by default, unless you're sending data - * in which case it's set accordingly to whatever is being sent - * (application/x-www-form-urlencoded, application/json or multipart/form-data). - * That is, of course, unless the option is passed, - * either here or through options.headers. - */ - content_type?: string; -} - -interface ResponseOptions { - /** - * Whether to decode the text responses to UTF-8, - * if Content-Type header shows a different charset. Defaults to true. - */ - decode_response?: boolean; - /** - * Alias for decode_response - */ - decode?: boolean; - - /** - * Whether to parse XML or JSON response bodies automagically. - * Defaults to true. - * You can also set this to 'xml' or 'json' in which case Needle - * will only parse the response if the content type matches. - */ - parse_response?: boolean; - /** - * Alias for parse_response - */ - parse?: boolean; - - /** - * Whether to parse response’s Set-Cookie header. - * Defaults to true. - * If parsed, response cookies will be available at resp.cookies. - */ - parse_cookies?: boolean; - /** - * Dump response output to file. - * This occurs after parsing and charset decoding is done. - */ - output?: string; -} - -interface RedirectOptions { - /** - * Sends the cookies received in the set-cookie header - * as part of the following request. - * false by default. - */ - follow_set_cookie?: boolean; - /** - * Sets the 'Referer' header to the requested URI - * when following a redirect. - * false by default. - */ - follow_set_referer?: boolean; - /** - * If enabled, resends the request using the original verb - * instead of being rewritten to get with no data. - * false by default. - */ - follow_keep_method?: boolean; - /** - * When true, Needle will only follow redirects that point to the same host - * as the original request. - * false by default. - */ - follow_if_same_host?: boolean; - /** - * When true, Needle will only follow redirects that point to the same protocol - * as the original request. - * false by default. - */ - follow_if_same_protocol?: boolean; -} - -interface KeyValue { - [key: string]: any; -} - -type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; +/** + * Calling needle() directly returns a Promise. + * + * Since needle 2.0 + * @param method Designates an HTTP verb for the request. + */ +declare function needle(method: core.NeedleReadonlyHttpVerbs, url: string, options?: core.NeedleOptions): Promise +/** + * Calling needle() directly returns a Promise. + * + * Since needle 2.0 + * @param method Designates an HTTP verb for the request. + * @param data May be null when issuing an HTTP DELETE request, but you need to explicity pass it. + */ +declare function needle(method: core.NeedleHttpVerbs, url: string, data: core.BodyData, options?: core.NeedleOptions): Promise declare namespace needle { + type BodyData = core.BodyData; + interface NeedleCallback extends core.NeedleCallback { } + type NeedleHttpVerbs = core.NeedleHttpVerbs; + export interface NeedleOptions extends core.NeedleOptions { } + interface ReadableStream extends core.ReadableStream { } + /** * Lets override the defaults for all future requests. */ @@ -282,7 +312,7 @@ declare namespace needle { * unless you pass a json: true option. * @param method Designates an HTTP verb for the request. */ - export function request(method: string, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + export function request(method: NeedleHttpVerbs, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; /** * Generic request. * This not only allows for flexibility, but also lets you perform a GET request with data, @@ -290,7 +320,7 @@ declare namespace needle { * unless you pass a json: true option. * @param method Designates an HTTP verb for the request. */ - export function request(method: string, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + export function request(method: NeedleHttpVerbs, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; } export = needle; \ No newline at end of file diff --git a/types/needle/needle-tests.ts b/types/needle/needle-tests.ts index 1c5090027a..268e64b23e 100644 --- a/types/needle/needle-tests.ts +++ b/types/needle/needle-tests.ts @@ -2,6 +2,10 @@ import * as needle from "needle"; import * as fs from "fs"; function Usage() { + // using promises + needle('get', 'http://ifconfig.me/all.json') + .then((resp) => console.log(resp.body.ip_addr)); + // using callback needle.get('http://ifconfig.me/all.json', function (error, response) { if (!error) @@ -9,16 +13,25 @@ function Usage() { }); // using streams - var out: any; // = fs.createWriteStream('logo.png'); + var out: any; needle.get('https://google.com/images/logo.png').pipe(out); } function ResponsePipeline() { + // using promises + needle('get', 'http://stackoverflow.com/feeds', { compressed: true }) + .then((resp) => { + console.log(resp.body); // this little guy won't be a Gzipped binary blob + // but a nice object containing all the latest entries + }); + + // using callback needle.get('http://stackoverflow.com/feeds', { compressed: true }, function (err, resp) { console.log(resp.body); // this little guy won't be a Gzipped binary blob // but a nice object containing all the latest entries }); + // using streams var options = { compressed: true, follow: 5, @@ -36,17 +49,19 @@ function ResponsePipeline() { } }); - stream.on('end', function(err: any) { + stream.on('end', function (err: any) { // if our request had an error, our 'end' event will tell us. if (!err) console.log('Great success!'); }) } function API_head() { - var options = { - open_timeout: 5000 // if we don't get a response in 5 seconds, boom. - }; + // using promises + needle('head', 'https://my.backend.server.com') + .then((resp) => console.log('Yup, still alive.')) + .catch((err: Error) => console.log('Shoot! Something is wrong: ' + err.message)); + // using callback needle.head('https://my.backend.server.com', function (err, resp) { if (err) { console.log('Shoot! Something is wrong: ' + err.message); @@ -58,6 +73,13 @@ function API_head() { } function API_get() { + // using promises + needle('get', 'google.com/search?q=syd+barrett') + .then((resp) => { + // if no http:// is found, Needle will automagically prepend it. + }); + + // using callback needle.get('google.com/search?q=syd+barrett', function (err, resp) { // if no http:// is found, Needle will automagically prepend it. }); @@ -68,6 +90,13 @@ function API_post() { headers: { 'X-Custom-Header': 'Bumbaway atuna' } }; + // using promises + needle('post', 'https://my.app.com/endpoint', 'foo=bar', options) + .then((resp) => { + // you can pass params as a string or as an object. + }); + + // using callback needle.post('https://my.app.com/endpoint', 'foo=bar', options, function (err, resp) { // you can pass params as a string or as an object. }); @@ -82,6 +111,13 @@ function API_put() { } }; + // using promises + needle('put', 'https://api.app.com/v2', nested) + .then((resp) => { + console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella. + }); + + // using callback needle.put('https://api.app.com/v2', nested, function (err, resp) { console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella. }); @@ -93,6 +129,13 @@ function API_delete() { password: 'x' }; + // using promises + needle('delete', 'https://api.app.com/messages/123', null, options) + .then((resp) => { + // in this case, data may be null, but you need to explicity pass it. + }); + + // using callback needle.delete('https://api.app.com/messages/123', null, options, function (err, resp) { // in this case, data may be null, but you need to explicity pass it. }); @@ -104,39 +147,78 @@ function API_request() { page: 2, }; + // using promises + needle('get', 'forum.com/search', params) + .then((resp) => { + if (resp.statusCode == 200) + console.log(resp.body); // here you go, mister. + }); + + needle('get', 'forum.com/search', params, { json: true }) + .then((resp) => { + if (resp.statusCode == 200) console.log('It worked!'); + }); + + // using callback needle.request('get', 'forum.com/search', params, function (err, resp) { if (!err && resp.statusCode == 200) console.log(resp.body); // here you go, mister. }); - needle.request('get', 'forum.com/search', params, { json: true }, function(err, resp) { + needle.request('get', 'forum.com/search', params, { json: true }, function (err, resp) { if (resp.statusCode == 200) console.log('It worked!'); }); } function HttpGetWithBasicAuth() { - needle.get('https://api.server.com', { username: 'you', password: 'secret' }, function(err, resp) { + // using promises + needle('get', 'https://api.server.com', { username: 'you', password: 'secret' }) + .then((resp) => { + // used HTTP auth + }); + needle('get', 'https://username:password@api.server.com') + .then((resp) => { + // used HTTP auth from URL + }); + + // using callback + needle.get('https://api.server.com', { username: 'you', password: 'secret' }, function (err, resp) { // used HTTP auth }); - needle.get('https://username:password@api.server.com', function(err, resp) { + needle.get('https://username:password@api.server.com', function (err, resp) { // used HTTP auth from URL }); } function DigestAuth() { - needle.get('other.server.com', { username: 'you', password: 'secret', auth: 'digest' }, function(err, resp, body) { + // using promises + needle('get', 'other.server.com', { username: 'you', password: 'secret', auth: 'digest' }) + .then((resp) => { + // needle prepends 'http://' to your URL, if missing + }); + + // using callback + needle.get('other.server.com', { username: 'you', password: 'secret', auth: 'digest' }, function (err, resp, body) { // needle prepends 'http://' to your URL, if missing }); } function CustomAcceptHeaderDeflate() { - var options = { + var options: needle.NeedleOptions = { compressed: true, follow: 10, accept: 'application/vnd.github.full+json' } - needle.get('api.github.com/users/tomas', options, function(err, resp, body) { + // using promises + needle('get', 'api.github.com/users/tomas', options) + .then((resp) => { + // body will contain a JSON.parse(d) object + // if parsing fails, you'll simply get the original body + }); + + // using callback + needle.get('api.github.com/users/tomas', options, function (err, resp, body) { // body will contain a JSON.parse(d) object // if parsing fails, you'll simply get the original body }); @@ -144,25 +226,41 @@ function CustomAcceptHeaderDeflate() { } function Various() { + // using promises + needle('get', 'https://news.ycombinator.com/rss') + .then((resp) => { + // if xml2js is installed, you'll get a nice object containing the nodes in the RSS + }); + needle('get', 'http://upload.server.com/tux.png', { output: '/tmp/tux.png' }) + .then((resp) => { + // you can dump any response to a file, not only binaries. + }); + needle('get', 'http://search.npmjs.org', { proxy: 'http://localhost:1234' }) + .then((resp) => { + // request passed through proxy + }); - needle.get('https://news.ycombinator.com/rss', function(err, resp, body) { + // using callback + needle.get('https://news.ycombinator.com/rss', function (err, resp, body) { // if xml2js is installed, you'll get a nice object containing the nodes in the RSS }); - needle.get('http://upload.server.com/tux.png', { output: '/tmp/tux.png' }, function(err, resp, body) { + needle.get('http://upload.server.com/tux.png', { output: '/tmp/tux.png' }, function (err, resp, body) { // you can dump any response to a file, not only binaries. }); - needle.get('http://search.npmjs.org', { proxy: 'http://localhost:1234' }, function(err, resp, body) { + needle.get('http://search.npmjs.org', { proxy: 'http://localhost:1234' }, function (err, resp, body) { // request passed through proxy }); + + // using streams const stream1 = needle.get('http://www.as35662.net/100.log'); - stream1.on('readable', function() { + stream1.on('readable', function () { let chunk: any; while (chunk = stream1.read()) { console.log('got data: ', chunk); } }); const stream2 = needle.get('http://jsonplaceholder.typicode.com/db', { parse: true }); - stream2.on('readable', function() { + stream2.on('readable', function () { let node: any; // our stream2 will only emit a single JSON root node. @@ -170,15 +268,6 @@ function Various() { console.log('got data: ', node); } }); - - /* - // Sample omitted, no JSONStream - needle.get('http://jsonplaceholder.typicode.com/db', { parse: true }) - .pipe(new JSONStream.parse('posts.*.title')) - .on('data', function (obj) { - console.log('got post title: %s', obj); - }); - */ } function FileUpload() { @@ -187,10 +276,21 @@ function FileUpload() { image: { file: '/home/tomas/linux.png', content_type: 'image/png' } }; - needle.post('http://my.other.app.com', data, { multipart: true }, function(err, resp, body) { + // using promises + needle('post', 'http://my.other.app.com', data, { multipart: true }) + .then((resp) => { + // needle will read the file and include it in the form-data as binary + }); + needle('put', 'https://api.app.com/v2', fs.createReadStream('myfile.txt')) + .then((resp) => { + // stream content is uploaded verbatim + }); + + // using callback + needle.post('http://my.other.app.com', data, { multipart: true }, function (err, resp, body) { // needle will read the file and include it in the form-data as binary }); - needle.put('https://api.app.com/v2', fs.createReadStream('myfile.txt'), function(err, resp, body) { + needle.put('https://api.app.com/v2', fs.createReadStream('myfile.txt'), function (err, resp, body) { // stream content is uploaded verbatim }); } @@ -206,7 +306,16 @@ function Multipart() { } } - needle.post('http://somewhere.com/over/the/rainbow', data, { multipart: true }, function(err, resp, body) { + // using promises + needle('post', 'http://somewhere.com/over/the/rainbow', data, { multipart: true }) + .then((resp) => { + // if you see, when using buffers we need to pass the filename for the multipart body. + // you can also pass a filename when using the file path method, in case you want to override + // the default filename to be received on the other end. + }); + + // using callback + needle.post('http://somewhere.com/over/the/rainbow', data, { multipart: true }, function (err, resp, body) { // if you see, when using buffers we need to pass the filename for the multipart body. // you can also pass a filename when using the file path method, in case you want to override // the default filename to be received on the other end. @@ -222,7 +331,15 @@ function MultipartContentType() { } } - needle.post('http://test.com/', data, { timeout: 5000, multipart: true }, function(err, resp, body) { + // using promises + needle('post', 'http://test.com/', data, { timeout: 5000, multipart: true }) + .then((resp) => { + // in this case, if the request takes more than 5 seconds + // the callback will return a [Socket closed] error + }); + + // using callback + needle.post('http://test.com/', data, { timeout: 5000, multipart: true }, function (err, resp, body) { // in this case, if the request takes more than 5 seconds // the callback will return a [Socket closed] error }); From 93f5c90355739d6736bbcd34c7712be2b67a7cce Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Fri, 1 Sep 2017 15:45:11 +0300 Subject: [PATCH 07/10] Adding tslint configuration --- types/needle/tslint.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 types/needle/tslint.json diff --git a/types/needle/tslint.json b/types/needle/tslint.json new file mode 100644 index 0000000000..7313bfcd80 --- /dev/null +++ b/types/needle/tslint.json @@ -0,0 +1,8 @@ +{ + "extends": "dtslint/dt.json", + "rules": { + "no-conditional-assignment": false, + "no-empty-interface": false, + "strict-export-declare-modifiers": false + } +} \ No newline at end of file From bc432e91e723840fbc29d7b96cdc9669b1ebe43c Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Fri, 1 Sep 2017 15:48:53 +0300 Subject: [PATCH 08/10] Make tslint rules for needle follow the repository defaults as much as possible --- types/needle/tslint.json | 1 - 1 file changed, 1 deletion(-) diff --git a/types/needle/tslint.json b/types/needle/tslint.json index 7313bfcd80..70429c253f 100644 --- a/types/needle/tslint.json +++ b/types/needle/tslint.json @@ -2,7 +2,6 @@ "extends": "dtslint/dt.json", "rules": { "no-conditional-assignment": false, - "no-empty-interface": false, "strict-export-declare-modifiers": false } } \ No newline at end of file From 805c421c26c007ff51869089101fa89c0aad5430 Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Fri, 1 Sep 2017 15:50:38 +0300 Subject: [PATCH 09/10] Fixing code to conform to tslint rules --- types/needle/index.d.ts | 17 +++--- types/needle/needle-tests.ts | 100 +++++++++++++++++------------------ 2 files changed, 58 insertions(+), 59 deletions(-) diff --git a/types/needle/index.d.ts b/types/needle/index.d.ts index 097cc8ba08..cc3fa4ff32 100644 --- a/types/needle/index.d.ts +++ b/types/needle/index.d.ts @@ -2,6 +2,7 @@ // Project: https://github.com/tomas/needle // Definitions by: San Chen , Niklas Mollenhauer , Matanel Sindilevich // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 /// @@ -223,26 +224,26 @@ declare namespace core { /** * Calling needle() directly returns a Promise. - * + * * Since needle 2.0 * @param method Designates an HTTP verb for the request. */ -declare function needle(method: core.NeedleReadonlyHttpVerbs, url: string, options?: core.NeedleOptions): Promise +declare function needle(method: core.NeedleReadonlyHttpVerbs, url: string, options?: core.NeedleOptions): Promise; /** * Calling needle() directly returns a Promise. - * + * * Since needle 2.0 * @param method Designates an HTTP verb for the request. * @param data May be null when issuing an HTTP DELETE request, but you need to explicity pass it. */ -declare function needle(method: core.NeedleHttpVerbs, url: string, data: core.BodyData, options?: core.NeedleOptions): Promise +declare function needle(method: core.NeedleHttpVerbs, url: string, data: core.BodyData, options?: core.NeedleOptions): Promise; declare namespace needle { type BodyData = core.BodyData; - interface NeedleCallback extends core.NeedleCallback { } + type NeedleCallback = core.NeedleCallback; type NeedleHttpVerbs = core.NeedleHttpVerbs; - export interface NeedleOptions extends core.NeedleOptions { } - interface ReadableStream extends core.ReadableStream { } + export type NeedleOptions = core.NeedleOptions; + type ReadableStream = core.ReadableStream; /** * Lets override the defaults for all future requests. @@ -323,4 +324,4 @@ declare namespace needle { export function request(method: NeedleHttpVerbs, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; } -export = needle; \ No newline at end of file +export = needle; diff --git a/types/needle/needle-tests.ts b/types/needle/needle-tests.ts index 268e64b23e..e8f2efee20 100644 --- a/types/needle/needle-tests.ts +++ b/types/needle/needle-tests.ts @@ -7,13 +7,13 @@ function Usage() { .then((resp) => console.log(resp.body.ip_addr)); // using callback - needle.get('http://ifconfig.me/all.json', function (error, response) { + needle.get('http://ifconfig.me/all.json', (error, response) => { if (!error) console.log(response.body.ip_addr); // JSON decoding magic. :) }); // using streams - var out: any; + const out = fs.createWriteStream('file.txt'); needle.get('https://google.com/images/logo.png').pipe(out); } @@ -26,13 +26,13 @@ function ResponsePipeline() { }); // using callback - needle.get('http://stackoverflow.com/feeds', { compressed: true }, function (err, resp) { + needle.get('http://stackoverflow.com/feeds', { compressed: true }, (err, resp) => { console.log(resp.body); // this little guy won't be a Gzipped binary blob // but a nice object containing all the latest entries }); // using streams - var options = { + const options = { compressed: true, follow: 5, rejectUnauthorized: true @@ -40,19 +40,19 @@ function ResponsePipeline() { // in this case, we'll ask Needle to follow redirects (disabled by default), // but also to verify their SSL certificates when connecting. - var stream = needle.get('https://backend.server.com/everything.html', options); + const stream = needle.get('https://backend.server.com/everything.html', options); - stream.on('readable', function () { - var data: any; + stream.on('readable', () => { + let data: any; while (data = stream.read()) { console.log(data.toString()); } }); - stream.on('end', function (err: any) { + stream.on('end', (err: any) => { // if our request had an error, our 'end' event will tell us. if (!err) console.log('Great success!'); - }) + }); } function API_head() { @@ -62,11 +62,10 @@ function API_head() { .catch((err: Error) => console.log('Shoot! Something is wrong: ' + err.message)); // using callback - needle.head('https://my.backend.server.com', function (err, resp) { + needle.head('https://my.backend.server.com', (err, resp) => { if (err) { console.log('Shoot! Something is wrong: ' + err.message); - } - else { + } else { console.log('Yup, still alive.'); } }); @@ -80,13 +79,13 @@ function API_get() { }); // using callback - needle.get('google.com/search?q=syd+barrett', function (err, resp) { + needle.get('google.com/search?q=syd+barrett', (err, resp) => { // if no http:// is found, Needle will automagically prepend it. }); } function API_post() { - var options = { + const options = { headers: { 'X-Custom-Header': 'Bumbaway atuna' } }; @@ -97,13 +96,13 @@ function API_post() { }); // using callback - needle.post('https://my.app.com/endpoint', 'foo=bar', options, function (err, resp) { + needle.post('https://my.app.com/endpoint', 'foo=bar', options, (err, resp) => { // you can pass params as a string or as an object. }); } function API_put() { - var nested = { + const nested = { params: { are: { also: 'supported' @@ -114,17 +113,17 @@ function API_put() { // using promises needle('put', 'https://api.app.com/v2', nested) .then((resp) => { - console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella. + console.log(`Got ${resp.bytes} bytes.`); // another nice treat from this handsome fella. }); // using callback - needle.put('https://api.app.com/v2', nested, function (err, resp) { - console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella. + needle.put('https://api.app.com/v2', nested, (err, resp) => { + console.log(`Got ${resp.bytes} bytes.`); // another nice treat from this handsome fella. }); } function API_delete() { - var options = { + const options = { username: 'fidelio', password: 'x' }; @@ -136,13 +135,13 @@ function API_delete() { }); // using callback - needle.delete('https://api.app.com/messages/123', null, options, function (err, resp) { + needle.delete('https://api.app.com/messages/123', null, options, (err, resp) => { // in this case, data may be null, but you need to explicity pass it. }); } function API_request() { - var params = { + const params = { q: 'a very smart query', page: 2, }; @@ -150,23 +149,23 @@ function API_request() { // using promises needle('get', 'forum.com/search', params) .then((resp) => { - if (resp.statusCode == 200) + if (resp.statusCode === 200) console.log(resp.body); // here you go, mister. }); needle('get', 'forum.com/search', params, { json: true }) .then((resp) => { - if (resp.statusCode == 200) console.log('It worked!'); + if (resp.statusCode === 200) console.log('It worked!'); }); // using callback - needle.request('get', 'forum.com/search', params, function (err, resp) { - if (!err && resp.statusCode == 200) + needle.request('get', 'forum.com/search', params, (err, resp) => { + if (!err && resp.statusCode === 200) console.log(resp.body); // here you go, mister. }); - needle.request('get', 'forum.com/search', params, { json: true }, function (err, resp) { - if (resp.statusCode == 200) console.log('It worked!'); + needle.request('get', 'forum.com/search', params, { json: true }, (err, resp) => { + if (resp.statusCode === 200) console.log('It worked!'); }); } @@ -182,10 +181,10 @@ function HttpGetWithBasicAuth() { }); // using callback - needle.get('https://api.server.com', { username: 'you', password: 'secret' }, function (err, resp) { + needle.get('https://api.server.com', { username: 'you', password: 'secret' }, (err, resp) => { // used HTTP auth }); - needle.get('https://username:password@api.server.com', function (err, resp) { + needle.get('https://username:password@api.server.com', (err, resp) => { // used HTTP auth from URL }); } @@ -198,17 +197,17 @@ function DigestAuth() { }); // using callback - needle.get('other.server.com', { username: 'you', password: 'secret', auth: 'digest' }, function (err, resp, body) { + needle.get('other.server.com', { username: 'you', password: 'secret', auth: 'digest' }, (err, resp, body) => { // needle prepends 'http://' to your URL, if missing }); } function CustomAcceptHeaderDeflate() { - var options: needle.NeedleOptions = { + const options: needle.NeedleOptions = { compressed: true, follow: 10, accept: 'application/vnd.github.full+json' - } + }; // using promises needle('get', 'api.github.com/users/tomas', options) @@ -218,11 +217,10 @@ function CustomAcceptHeaderDeflate() { }); // using callback - needle.get('api.github.com/users/tomas', options, function (err, resp, body) { + needle.get('api.github.com/users/tomas', options, (err, resp, body) => { // body will contain a JSON.parse(d) object // if parsing fails, you'll simply get the original body }); - } function Various() { @@ -241,26 +239,26 @@ function Various() { }); // using callback - needle.get('https://news.ycombinator.com/rss', function (err, resp, body) { + needle.get('https://news.ycombinator.com/rss', (err, resp, body) => { // if xml2js is installed, you'll get a nice object containing the nodes in the RSS }); - needle.get('http://upload.server.com/tux.png', { output: '/tmp/tux.png' }, function (err, resp, body) { + needle.get('http://upload.server.com/tux.png', { output: '/tmp/tux.png' }, (err, resp, body) => { // you can dump any response to a file, not only binaries. }); - needle.get('http://search.npmjs.org', { proxy: 'http://localhost:1234' }, function (err, resp, body) { + needle.get('http://search.npmjs.org', { proxy: 'http://localhost:1234' }, (err, resp, body) => { // request passed through proxy }); // using streams const stream1 = needle.get('http://www.as35662.net/100.log'); - stream1.on('readable', function () { + stream1.on('readable', () => { let chunk: any; while (chunk = stream1.read()) { console.log('got data: ', chunk); } }); const stream2 = needle.get('http://jsonplaceholder.typicode.com/db', { parse: true }); - stream2.on('readable', function () { + stream2.on('readable', () => { let node: any; // our stream2 will only emit a single JSON root node. @@ -271,7 +269,7 @@ function Various() { } function FileUpload() { - var data = { + const data = { foo: 'bar', image: { file: '/home/tomas/linux.png', content_type: 'image/png' } }; @@ -287,24 +285,24 @@ function FileUpload() { }); // using callback - needle.post('http://my.other.app.com', data, { multipart: true }, function (err, resp, body) { + needle.post('http://my.other.app.com', data, { multipart: true }, (err, resp, body) => { // needle will read the file and include it in the form-data as binary }); - needle.put('https://api.app.com/v2', fs.createReadStream('myfile.txt'), function (err, resp, body) { + needle.put('https://api.app.com/v2', fs.createReadStream('myfile.txt'), (err, resp, body) => { // stream content is uploaded verbatim }); } function Multipart() { - var buffer = fs.readFileSync('/path/to/package.zip'); + const buffer = fs.readFileSync('/path/to/package.zip'); - var data = { + const data = { zip_file: { - buffer: buffer, + buffer, filename: 'mypackage.zip', content_type: 'application/octet-stream' } - } + }; // using promises needle('post', 'http://somewhere.com/over/the/rainbow', data, { multipart: true }) @@ -315,7 +313,7 @@ function Multipart() { }); // using callback - needle.post('http://somewhere.com/over/the/rainbow', data, { multipart: true }, function (err, resp, body) { + needle.post('http://somewhere.com/over/the/rainbow', data, { multipart: true }, (err, resp, body) => { // if you see, when using buffers we need to pass the filename for the multipart body. // you can also pass a filename when using the file path method, in case you want to override // the default filename to be received on the other end. @@ -323,13 +321,13 @@ function Multipart() { } function MultipartContentType() { - var data = { + const data = { token: 'verysecret', payload: { value: JSON.stringify({ title: 'test', version: 1 }), content_type: 'application/json' } - } + }; // using promises needle('post', 'http://test.com/', data, { timeout: 5000, multipart: true }) @@ -339,7 +337,7 @@ function MultipartContentType() { }); // using callback - needle.post('http://test.com/', data, { timeout: 5000, multipart: true }, function (err, resp, body) { + needle.post('http://test.com/', data, { timeout: 5000, multipart: true }, (err, resp, body) => { // in this case, if the request takes more than 5 seconds // the callback will return a [Socket closed] error }); From a0e932d3c6741e1fb19ec6d164e56e0316400f78 Mon Sep 17 00:00:00 2001 From: Matanel Sindilevich Date: Thu, 7 Sep 2017 21:46:52 +0300 Subject: [PATCH 10/10] Preserving needle v1.x definitions --- types/needle/v1/index.d.ts | 118 ++++++++++++++++ types/needle/v1/needle-tests.ts | 229 ++++++++++++++++++++++++++++++++ types/needle/v1/tsconfig.json | 25 ++++ 3 files changed, 372 insertions(+) create mode 100644 types/needle/v1/index.d.ts create mode 100644 types/needle/v1/needle-tests.ts create mode 100644 types/needle/v1/tsconfig.json diff --git a/types/needle/v1/index.d.ts b/types/needle/v1/index.d.ts new file mode 100644 index 0000000000..8cc61f2a2f --- /dev/null +++ b/types/needle/v1/index.d.ts @@ -0,0 +1,118 @@ +// Type definitions for needle 1.4 +// Project: https://github.com/tomas/needle +// Definitions by: San Chen , Niklas Mollenhauer +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module "needle" { + import * as http from 'http'; + import * as Buffer from 'buffer'; + import * as https from 'https'; + namespace Needle { + interface NeedleResponse extends http.IncomingMessage { + body: any; + raw: Buffer; + bytes: number; + } + + type ReadableStream = NodeJS.ReadableStream; + + type NeedleCallback = (error: Error, response: NeedleResponse, body: any) => void; + + interface Cookies { + [name: string]: any; + } + + type NeedleOptions = RequestOptions & ResponseOptions & RedirectOptions & https.RequestOptions; + + interface RequestOptions { + open_timeout?: number; + read_timeout?: number; + /** + * Alias for open_timeout + */ + timeout?: number; + + follow_max?: number; + /** + * Alias for follow_max + */ + follow?: number; + + multipart?: boolean; + agent?: http.Agent | boolean; + proxy?: string; + headers?: {}; + auth?: "auto" | "digest" | "basic"; + json?: boolean; + + // These properties are overwritten by those in the 'headers' field + cookies?: Cookies; + compressed?: boolean; + // Overwritten if present in the URI + username?: string; + password?: string; + accept?: string; + connection?: string; + user_agent?: string; + } + + interface ResponseOptions { + decode_response?: boolean; + /** + * Alias for decode_response + */ + decode?: boolean; + parse_response?: boolean; + /** + * Alias for parse_response + */ + parse?: boolean; + + parse_cookies?: boolean; + output?: string; + } + + interface RedirectOptions { + follow_set_cookie?: boolean; + follow_set_referer?: boolean; + follow_keep_method?: boolean; + follow_if_same_host?: boolean; + follow_if_same_protocol?: boolean; + } + + interface KeyValue { + [key: string]: any; + } + + type BodyData = Buffer | KeyValue | NodeJS.ReadableStream | string | null; + + interface NeedleStatic { + defaults(options: NeedleOptions): void; + + head(url: string, callback?: NeedleCallback): ReadableStream; + head(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + + get(url: string, callback?: NeedleCallback): ReadableStream; + get(url: string, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + + post(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + post(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + + put(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + put(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + + patch(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + patch(url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + + delete(url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + delete(url: string, data: BodyData, options?: NeedleOptions, callback ?: NeedleCallback): ReadableStream; + + request(method: string, url: string, data: BodyData, callback?: NeedleCallback): ReadableStream; + request(method: string, url: string, data: BodyData, options?: NeedleOptions, callback?: NeedleCallback): ReadableStream; + } + } + const needle: Needle.NeedleStatic; + export = needle; +} diff --git a/types/needle/v1/needle-tests.ts b/types/needle/v1/needle-tests.ts new file mode 100644 index 0000000000..1c5090027a --- /dev/null +++ b/types/needle/v1/needle-tests.ts @@ -0,0 +1,229 @@ +import * as needle from "needle"; +import * as fs from "fs"; + +function Usage() { + // using callback + needle.get('http://ifconfig.me/all.json', function (error, response) { + if (!error) + console.log(response.body.ip_addr); // JSON decoding magic. :) + }); + + // using streams + var out: any; // = fs.createWriteStream('logo.png'); + needle.get('https://google.com/images/logo.png').pipe(out); +} + +function ResponsePipeline() { + needle.get('http://stackoverflow.com/feeds', { compressed: true }, function (err, resp) { + console.log(resp.body); // this little guy won't be a Gzipped binary blob + // but a nice object containing all the latest entries + }); + + var options = { + compressed: true, + follow: 5, + rejectUnauthorized: true + }; + + // in this case, we'll ask Needle to follow redirects (disabled by default), + // but also to verify their SSL certificates when connecting. + var stream = needle.get('https://backend.server.com/everything.html', options); + + stream.on('readable', function () { + var data: any; + while (data = stream.read()) { + console.log(data.toString()); + } + }); + + stream.on('end', function(err: any) { + // if our request had an error, our 'end' event will tell us. + if (!err) console.log('Great success!'); + }) +} + +function API_head() { + var options = { + open_timeout: 5000 // if we don't get a response in 5 seconds, boom. + }; + + needle.head('https://my.backend.server.com', function (err, resp) { + if (err) { + console.log('Shoot! Something is wrong: ' + err.message); + } + else { + console.log('Yup, still alive.'); + } + }); +} + +function API_get() { + needle.get('google.com/search?q=syd+barrett', function (err, resp) { + // if no http:// is found, Needle will automagically prepend it. + }); +} + +function API_post() { + var options = { + headers: { 'X-Custom-Header': 'Bumbaway atuna' } + }; + + needle.post('https://my.app.com/endpoint', 'foo=bar', options, function (err, resp) { + // you can pass params as a string or as an object. + }); +} + +function API_put() { + var nested = { + params: { + are: { + also: 'supported' + } + } + }; + + needle.put('https://api.app.com/v2', nested, function (err, resp) { + console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella. + }); +} + +function API_delete() { + var options = { + username: 'fidelio', + password: 'x' + }; + + needle.delete('https://api.app.com/messages/123', null, options, function (err, resp) { + // in this case, data may be null, but you need to explicity pass it. + }); +} + +function API_request() { + var params = { + q: 'a very smart query', + page: 2, + }; + + needle.request('get', 'forum.com/search', params, function (err, resp) { + if (!err && resp.statusCode == 200) + console.log(resp.body); // here you go, mister. + }); + + needle.request('get', 'forum.com/search', params, { json: true }, function(err, resp) { + if (resp.statusCode == 200) console.log('It worked!'); + }); +} + +function HttpGetWithBasicAuth() { + needle.get('https://api.server.com', { username: 'you', password: 'secret' }, function(err, resp) { + // used HTTP auth + }); + needle.get('https://username:password@api.server.com', function(err, resp) { + // used HTTP auth from URL + }); +} + +function DigestAuth() { + needle.get('other.server.com', { username: 'you', password: 'secret', auth: 'digest' }, function(err, resp, body) { + // needle prepends 'http://' to your URL, if missing + }); +} + +function CustomAcceptHeaderDeflate() { + var options = { + compressed: true, + follow: 10, + accept: 'application/vnd.github.full+json' + } + + needle.get('api.github.com/users/tomas', options, function(err, resp, body) { + // body will contain a JSON.parse(d) object + // if parsing fails, you'll simply get the original body + }); + +} + +function Various() { + + needle.get('https://news.ycombinator.com/rss', function(err, resp, body) { + // if xml2js is installed, you'll get a nice object containing the nodes in the RSS + }); + needle.get('http://upload.server.com/tux.png', { output: '/tmp/tux.png' }, function(err, resp, body) { + // you can dump any response to a file, not only binaries. + }); + needle.get('http://search.npmjs.org', { proxy: 'http://localhost:1234' }, function(err, resp, body) { + // request passed through proxy + }); + const stream1 = needle.get('http://www.as35662.net/100.log'); + stream1.on('readable', function() { + let chunk: any; + while (chunk = stream1.read()) { + console.log('got data: ', chunk); + } + }); + const stream2 = needle.get('http://jsonplaceholder.typicode.com/db', { parse: true }); + stream2.on('readable', function() { + let node: any; + + // our stream2 will only emit a single JSON root node. + while (node = stream2.read()) { + console.log('got data: ', node); + } + }); + + /* + // Sample omitted, no JSONStream + needle.get('http://jsonplaceholder.typicode.com/db', { parse: true }) + .pipe(new JSONStream.parse('posts.*.title')) + .on('data', function (obj) { + console.log('got post title: %s', obj); + }); + */ +} + +function FileUpload() { + var data = { + foo: 'bar', + image: { file: '/home/tomas/linux.png', content_type: 'image/png' } + }; + + needle.post('http://my.other.app.com', data, { multipart: true }, function(err, resp, body) { + // needle will read the file and include it in the form-data as binary + }); + needle.put('https://api.app.com/v2', fs.createReadStream('myfile.txt'), function(err, resp, body) { + // stream content is uploaded verbatim + }); +} + +function Multipart() { + var buffer = fs.readFileSync('/path/to/package.zip'); + + var data = { + zip_file: { + buffer: buffer, + filename: 'mypackage.zip', + content_type: 'application/octet-stream' + } + } + + needle.post('http://somewhere.com/over/the/rainbow', data, { multipart: true }, function(err, resp, body) { + // if you see, when using buffers we need to pass the filename for the multipart body. + // you can also pass a filename when using the file path method, in case you want to override + // the default filename to be received on the other end. + }); +} + +function MultipartContentType() { + var data = { + token: 'verysecret', + payload: { + value: JSON.stringify({ title: 'test', version: 1 }), + content_type: 'application/json' + } + } + + needle.post('http://test.com/', data, { timeout: 5000, multipart: true }, function(err, resp, body) { + // in this case, if the request takes more than 5 seconds + // the callback will return a [Socket closed] error + }); +} diff --git a/types/needle/v1/tsconfig.json b/types/needle/v1/tsconfig.json new file mode 100644 index 0000000000..f6b8b1e810 --- /dev/null +++ b/types/needle/v1/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../../", + "typeRoots": [ + "../../" + ], + "paths": { + "needle": ["needle/v1"] + }, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "needle-tests.ts" + ] +}