From 29ac795c9a89e2c9379745689dc86adeba1fe0a5 Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Sun, 15 May 2016 22:07:45 -0400 Subject: [PATCH 1/7] Added basic Typescript definitions. --- fb.d.ts | 18 ++++++++++++++++++ package.json | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 fb.d.ts diff --git a/fb.d.ts b/fb.d.ts new file mode 100644 index 0000000..db459c9 --- /dev/null +++ b/fb.d.ts @@ -0,0 +1,18 @@ +declare class FB { + api(path:string, callback?:(response:any) => void):void; + api(path:string, params:any, callback?:(response:any) => void):void; + api(path:string, method:string, params:any, callback?:(response:any) => void):void; + napi(path:string, callback?:(error:any, response:any) => void):void; + napi(path:string, params:any, callback?:(error:any, response:any) => void):void; + napi(path:string, method:string, params:any, callback?:(error:any, response:any) => void):void; + getAccessToken(): string; + setAccessToken(token:string): void; + parseSignedRequest(signedRequest:string, appSecret?:string): any; + getLoginUrl(options:any): string; + options(): any; + options(optionName:string): any; + options(optionsDict:any): void; + version: string; +} + +export = new FB \ No newline at end of file diff --git a/package.json b/package.json index 37a6fe3..3eb0c98 100644 --- a/package.json +++ b/package.json @@ -46,5 +46,6 @@ }, "engines": { "node": ">=0.10.0" - } + }, + "typings": "fb.d.ts" } From 0236577566892042669a017477a3d684b56ef4ca Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Mon, 23 May 2016 10:12:22 -0400 Subject: [PATCH 2/7] Updated to reflect changed API and what is actually exported from the module. --- es6-promise.d.ts | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ fb.d.ts | 39 ++++++++++++++-------- 2 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 es6-promise.d.ts diff --git a/es6-promise.d.ts b/es6-promise.d.ts new file mode 100644 index 0000000..001330f --- /dev/null +++ b/es6-promise.d.ts @@ -0,0 +1,84 @@ +// Type definitions for es6-promise +// Project: https://github.com/jakearchibald/ES6-Promise +// Definitions by: François de Campredon , vvakame +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +interface Thenable { + then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => U | Thenable): Thenable; + then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} + +declare class Promise implements Thenable { + /** + * If you call resolve in the body of the callback passed to the constructor, + * your promise is fulfilled with result object passed to resolve. + * If you call reject your promise is rejected with the object passed to reject. + * For consistency and debugging (eg stack traces), obj should be an instanceof Error. + * Any errors thrown in the constructor callback will be implicitly passed to reject(). + */ + constructor(callback: (resolve : (value?: T | Thenable) => void, reject: (error?: any) => void) => void); + + /** + * onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects. + * Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called. + * Both callbacks have a single parameter , the fulfillment value or rejection reason. + * "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. + * If an error is thrown in the callback, the returned promise rejects with that error. + * + * @param onFulfilled called when/if "promise" resolves + * @param onRejected called when/if "promise" rejects + */ + then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => U | Thenable): Promise; + then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => void): Promise; + + /** + * Sugar for promise.then(undefined, onRejected) + * + * @param onRejected called when/if "promise" rejects + */ + catch(onRejected?: (error: any) => U | Thenable): Promise; +} + +declare namespace Promise { + /** + * Make a new promise from the thenable. + * A thenable is promise-like in as far as it has a "then" method. + */ + function resolve(value?: T | Thenable): Promise; + + /** + * Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error + */ + function reject(error: any): Promise; + function reject(error: T): Promise; + + /** + * Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects. + * the array passed to all can be a mixture of promise-like objects and other objects. + * The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value. + */ + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable, T9 | Thenable, T10 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable, T9 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable]): Promise<[T1, T2, T3, T4, T5]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable ]): Promise<[T1, T2, T3, T4]>; + function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable]): Promise<[T1, T2, T3]>; + function all(values: [T1 | Thenable, T2 | Thenable]): Promise<[T1, T2]>; + function all(values: (T | Thenable)[]): Promise; + + /** + * Make a Promise that fulfills when any item fulfills, and rejects if any item rejects. + */ + function race(promises: (T | Thenable)[]): Promise; +} + +declare module 'es6-promise' { + var foo: typeof Promise; // Temp variable to reference Promise in local context + namespace rsvp { + export var Promise: typeof foo; + } + export = rsvp; +} diff --git a/fb.d.ts b/fb.d.ts index db459c9..f35d963 100644 --- a/fb.d.ts +++ b/fb.d.ts @@ -1,18 +1,29 @@ -declare class FB { - api(path:string, callback?:(response:any) => void):void; - api(path:string, params:any, callback?:(response:any) => void):void; - api(path:string, method:string, params:any, callback?:(response:any) => void):void; - napi(path:string, callback?:(error:any, response:any) => void):void; - napi(path:string, params:any, callback?:(error:any, response:any) => void):void; - napi(path:string, method:string, params:any, callback?:(error:any, response:any) => void):void; +/// +export class Facebook { + api(path: string): Promise; + api(path: string, callback: (response: any) => void): void; + api(path: string, params: any): Promise; + api(path: string, params: any, callback: (response: any) => void): void; + api(path: string, method: string, params: any): Promise; + api(path: string, method: string, params: any, callback: (response: any) => void): void; + napi(path: string, callback?: (error: any, response: any) => void): void; + napi(path: string, params: any, callback?: (error: any, response: any) => void): void; + napi(path: string, method: string, params: any, callback?: (error: any, response: any) => void): void; getAccessToken(): string; - setAccessToken(token:string): void; - parseSignedRequest(signedRequest:string, appSecret?:string): any; - getLoginUrl(options:any): string; + setAccessToken(token: string): void; + parseSignedRequest(signedRequest: string, appSecret?: string): any; + getLoginUrl(options: any): string; options(): any; - options(optionName:string): any; - options(optionsDict:any): void; - version: string; + options(optionName: string): any; + options(optionsDict: any): void; } -export = new FB \ No newline at end of file +export default new Facebook; +export var FB: Facebook; +export var version: string; + +export class FacebookApiException { + name: string; + message: string; + response: any; +} \ No newline at end of file From fd072b87dd6b2f238b53e4b5da82dab0e26fb52d Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Mon, 23 May 2016 10:18:21 -0400 Subject: [PATCH 3/7] Use dependency's Promise TS definition. --- es6-promise.d.ts | 84 ------------------------------------------------ fb.d.ts | 3 +- 2 files changed, 2 insertions(+), 85 deletions(-) delete mode 100644 es6-promise.d.ts diff --git a/es6-promise.d.ts b/es6-promise.d.ts deleted file mode 100644 index 001330f..0000000 --- a/es6-promise.d.ts +++ /dev/null @@ -1,84 +0,0 @@ -// Type definitions for es6-promise -// Project: https://github.com/jakearchibald/ES6-Promise -// Definitions by: François de Campredon , vvakame -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -interface Thenable { - then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => U | Thenable): Thenable; - then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => void): Thenable; - catch(onRejected?: (error: any) => U | Thenable): Thenable; -} - -declare class Promise implements Thenable { - /** - * If you call resolve in the body of the callback passed to the constructor, - * your promise is fulfilled with result object passed to resolve. - * If you call reject your promise is rejected with the object passed to reject. - * For consistency and debugging (eg stack traces), obj should be an instanceof Error. - * Any errors thrown in the constructor callback will be implicitly passed to reject(). - */ - constructor(callback: (resolve : (value?: T | Thenable) => void, reject: (error?: any) => void) => void); - - /** - * onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects. - * Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called. - * Both callbacks have a single parameter , the fulfillment value or rejection reason. - * "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. - * If an error is thrown in the callback, the returned promise rejects with that error. - * - * @param onFulfilled called when/if "promise" resolves - * @param onRejected called when/if "promise" rejects - */ - then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => U | Thenable): Promise; - then(onFulfilled?: (value: T) => U | Thenable, onRejected?: (error: any) => void): Promise; - - /** - * Sugar for promise.then(undefined, onRejected) - * - * @param onRejected called when/if "promise" rejects - */ - catch(onRejected?: (error: any) => U | Thenable): Promise; -} - -declare namespace Promise { - /** - * Make a new promise from the thenable. - * A thenable is promise-like in as far as it has a "then" method. - */ - function resolve(value?: T | Thenable): Promise; - - /** - * Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error - */ - function reject(error: any): Promise; - function reject(error: T): Promise; - - /** - * Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects. - * the array passed to all can be a mixture of promise-like objects and other objects. - * The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value. - */ - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable, T9 | Thenable, T10 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable, T9 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable, T8 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable, T7 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable, T6 | Thenable]): Promise<[T1, T2, T3, T4, T5, T6]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable , T5 | Thenable]): Promise<[T1, T2, T3, T4, T5]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable, T4 | Thenable ]): Promise<[T1, T2, T3, T4]>; - function all(values: [T1 | Thenable, T2 | Thenable, T3 | Thenable]): Promise<[T1, T2, T3]>; - function all(values: [T1 | Thenable, T2 | Thenable]): Promise<[T1, T2]>; - function all(values: (T | Thenable)[]): Promise; - - /** - * Make a Promise that fulfills when any item fulfills, and rejects if any item rejects. - */ - function race(promises: (T | Thenable)[]): Promise; -} - -declare module 'es6-promise' { - var foo: typeof Promise; // Temp variable to reference Promise in local context - namespace rsvp { - export var Promise: typeof foo; - } - export = rsvp; -} diff --git a/fb.d.ts b/fb.d.ts index f35d963..b3a9b78 100644 --- a/fb.d.ts +++ b/fb.d.ts @@ -1,4 +1,5 @@ -/// +import Promise = require("any-promise"); + export class Facebook { api(path: string): Promise; api(path: string, callback: (response: any) => void): void; From fe11fc426cbb16b6589ac90e6931d6df96a52220 Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Sun, 12 Jun 2016 12:29:50 -0400 Subject: [PATCH 4/7] Added missing methods, some option definitions. --- fb.d.ts | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/fb.d.ts b/fb.d.ts index b3a9b78..8ac7b5c 100644 --- a/fb.d.ts +++ b/fb.d.ts @@ -1,22 +1,53 @@ import Promise = require("any-promise"); +type HTTPMethods = "get" | "post" | "delete"; + +export interface FacebookOptions { + accessToken?: string; + appId?: string; + appSecret?: string; + version?: string; + proxy?: string; + timeout?: number; + scope?: string; + redirectUri?: string; + Promise?: any; +} + +export interface LoginUrlOptions { + appId?: string; + client_id?: string; + redirectUri?: string; + redirect_uri?: string; + scope?: string; + display?: string; + state?: string; + responseType?: string; + response_type?: string; +} + export class Facebook { api(path: string): Promise; api(path: string, callback: (response: any) => void): void; api(path: string, params: any): Promise; api(path: string, params: any, callback: (response: any) => void): void; - api(path: string, method: string, params: any): Promise; - api(path: string, method: string, params: any, callback: (response: any) => void): void; + api(path: string, method: HTTPMethods): Promise; + api(path: string, method: HTTPMethods, callback: (response: any) => void): void; + api(path: string, method: HTTPMethods, params: any): Promise; + api(path: string, method: HTTPMethods, params: any, callback: (response: any) => void): void; napi(path: string, callback?: (error: any, response: any) => void): void; napi(path: string, params: any, callback?: (error: any, response: any) => void): void; - napi(path: string, method: string, params: any, callback?: (error: any, response: any) => void): void; + napi(path: string, method: HTTPMethods, callback?: (error: any, response: any) => void): void; + napi(path: string, method: HTTPMethods, params: any, callback?: (error: any, response: any) => void): void; getAccessToken(): string; setAccessToken(token: string): void; parseSignedRequest(signedRequest: string, appSecret?: string): any; - getLoginUrl(options: any): string; - options(): any; + getLoginUrl(options?: LoginUrlOptions): string; + options(): FacebookOptions; options(optionName: string): any; - options(optionsDict: any): void; + options(optionsDict: FacebookOptions): void; + extend(options: FacebookOptions): Facebook; + withAccessToken(token: string): Facebook; } export default new Facebook; From caff308c2c38ea132b3748e5979d234185298ede Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Sun, 12 Jun 2016 22:01:13 -0400 Subject: [PATCH 5/7] Added test for typescript definition. --- package.json | 4 +++- test/typings/import.ts | 46 ++++++++++++++++++++++++++++++++++++++ test/typings/tsconfig.json | 3 +++ test/typings/typings.js | 18 +++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 test/typings/import.ts create mode 100644 test/typings/tsconfig.json create mode 100644 test/typings/typings.js diff --git a/package.json b/package.json index 9ed7b9b..e067a4b 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,9 @@ "lodash.omit": "^4.3.0", "mocha": "^2.4.5", "mocha-eslint": "^2.0.2", - "nock": "^8.0.0" + "nock": "^8.0.0", + "typescript": "^1.8.10", + "typescript-definition-tester": "0.0.4" }, "engines": { "node": ">=4" diff --git a/test/typings/import.ts b/test/typings/import.ts new file mode 100644 index 0000000..30b7a41 --- /dev/null +++ b/test/typings/import.ts @@ -0,0 +1,46 @@ +// so happy this relative import seems to work the same as ' import FB from "fb" ' +import FB from "../../"; +import {Facebook} from "../../"; + +// the 3 options overloads +FB.options().appId; +FB.options("appId"); +FB.options({ + appId: "alskjdfaslkdjfalsdfjk" +}); +// extend returns a Facebook +FB.extend({ + accessToken: "loremipsum" +}).options("accessToken"); +// withAccessToken returns a Facebook +FB.withAccessToken("foobar").options("accessToken"); +// setAccessToken works, getAccessToken returns a string +FB.setAccessToken("foobar"); +FB.getAccessToken().charAt(0); + +// All api calls have the documented parameters/returns +FB.api("./").then((response) => { +}); +FB.api("./", (response) => {}); +FB.api("./", {scope: "foo"}).then((response) => { +}); +FB.api("./", {scope: "foo"}, (response) => {}); +FB.api("./", "get").then((response) => { +}); +FB.api("./", "post", (response) => {}); +FB.api("./", "delete", {scope: "foo"}).then((response) => { +}); +FB.api("./", "get", {scope: "foo"}, (response) => {}); +// All napi calls have the coumented parameters +FB.napi("./"); +FB.napi("./", (error, response) => {}); +FB.napi("./", {scope: "foo"}); +FB.napi("./", {scope: "foo"}, (error, response) => {}); +FB.napi("./", "post"); +FB.napi("./", "post", (error, response) => {}); +FB.napi("./", "delete", {scope: "foo"}); +FB.napi("./", "delete", {scope: "foo"}, (error, response) => {}); + +// can instantiate Facebook class +let fb = new Facebook(); +fb.api("./"); \ No newline at end of file diff --git a/test/typings/tsconfig.json b/test/typings/tsconfig.json new file mode 100644 index 0000000..6abeaa6 --- /dev/null +++ b/test/typings/tsconfig.json @@ -0,0 +1,3 @@ +{ + "compileOnSave": false +} \ No newline at end of file diff --git a/test/typings/typings.js b/test/typings/typings.js new file mode 100644 index 0000000..b90a798 --- /dev/null +++ b/test/typings/typings.js @@ -0,0 +1,18 @@ +'use strict'; + +var tt = require('typescript-definition-tester'); + +describe('typescript definition tests', function() { + this.slow(1800); + this.timeout(2000); + it('should compile examples successfully against fb.d.ts', (done) => { + tt.compileDirectory( + __dirname, + function(fileName) { + return fileName.indexOf('.ts') > -1; + }, + function() { + done(); + }); + }); +}); From ba5e440aa9ff02f4dc7ba34fa3c86064b53dd7f1 Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Wed, 8 Feb 2017 10:33:13 -0500 Subject: [PATCH 6/7] Fix comma that got dropped during merge. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b99328a..ab0a9d5 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "lodash.omit": "^4.5.0", "mocha": "^3.2.0", "mocha-eslint": "^3.0.1", - "nock": "^9.0.2" + "nock": "^9.0.2", "typescript": "^1.8.10", "typescript-definition-tester": "0.0.4" }, From 8ffe919fd64d8094f796bd57aee2a5ff9d0288f8 Mon Sep 17 00:00:00 2001 From: Andrew Start Date: Wed, 8 Feb 2017 10:36:02 -0500 Subject: [PATCH 7/7] Clean up typings test --- test/typings/import.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/typings/import.ts b/test/typings/import.ts index 30b7a41..d0ed399 100644 --- a/test/typings/import.ts +++ b/test/typings/import.ts @@ -1,6 +1,5 @@ // so happy this relative import seems to work the same as ' import FB from "fb" ' -import FB from "../../"; -import {Facebook} from "../../"; +import FB, {Facebook} from "../../"; // the 3 options overloads FB.options().appId; @@ -31,7 +30,7 @@ FB.api("./", "post", (response) => {}); FB.api("./", "delete", {scope: "foo"}).then((response) => { }); FB.api("./", "get", {scope: "foo"}, (response) => {}); -// All napi calls have the coumented parameters +// All napi calls have the documented parameters FB.napi("./"); FB.napi("./", (error, response) => {}); FB.napi("./", {scope: "foo"}); @@ -43,4 +42,4 @@ FB.napi("./", "delete", {scope: "foo"}, (error, response) => {}); // can instantiate Facebook class let fb = new Facebook(); -fb.api("./"); \ No newline at end of file +fb.api("./");