From ac220e3ae2f76c9ead7d2bc76fd4d2c3cbd33a8f Mon Sep 17 00:00:00 2001 From: tkqubo Date: Sun, 20 Sep 2015 04:21:55 +0900 Subject: [PATCH] Add typings and test code from Pusher Documentation (https://pusher.com/docs) --- pusher-js/pusher-js-tests.ts | 265 +++++++++++++++++++++++++++++++++++ pusher-js/pusher-js.d.ts | 123 +++++++++++++++- 2 files changed, 381 insertions(+), 7 deletions(-) diff --git a/pusher-js/pusher-js-tests.ts b/pusher-js/pusher-js-tests.ts index a1c0429b0..c672ff58e 100644 --- a/pusher-js/pusher-js-tests.ts +++ b/pusher-js/pusher-js-tests.ts @@ -1,6 +1,7 @@ /// import Pusher = require('pusher-js'); +import { PresenceChannel } from "pusher-js"; var API_KEY: string; var pusher: Pusher.Pusher; @@ -86,3 +87,267 @@ channel.unbind(null, handler); // removes `handler` for all events channel.unbind(null, null, context); // removes all handlers for `context` channel.unbind(); // removes all handlers on `channel` + +// +// +// Samples from Pusher Documentation +// +// + +// +// JavaScript Quick Start Guide +// + +channel.bind('my-event', function(data: any) { + alert('An event was triggered with message: ' + data.message); +}); + +// +// Client API Overview +// + +var options: Pusher.Config; + +var channelName: string; +var privateChannelName: string; +var presenceChannelName: string; +var add_member: Function; +var remove_member: Function; +var update_member_count: Function; +var eventName: string; +var callback: Function; +var applicationKey: string; +var log: Function; +var $: any; +var data: any; + +// Connecting to Pusher + +pusher = new Pusher(applicationKey, options); + +options = { + encrypted: true, // true/false + auth: { + params: { // {key: value} pairs + param1: 'value1', + param2: 'value2' + }, + headers: { // {key: value} pairs + header1: 'value1', + header2: 'value2' + } + } +}; + +pusher = new Pusher('app_key', { + auth: { + params: { + CSRFToken: 'some_csrf_token' + } + } +}); + +pusher = new Pusher('app_key', { + auth: { + headers: { + 'X-CSRF-Token': 'some_csrf_token' + } + } +}); + +pusher = new Pusher('app_key', { cluster: 'eu' }); + +pusher = new Pusher('app_key', { encrypted: true } ); + +pusher = new Pusher('app_key'); +pusher.connection.bind( 'error', function( err: any ) { + if( err.data.code === 4004 ) { + log('>>> detected limit error'); + } +}); + +// Disconnecting from Pusher + +pusher.disconnect(); + +// Connection States + +pusher = new Pusher('YOUR_APP_KEY'); + +pusher.connection.bind('connected', function() { + $('div#status').text('Real time is go!'); +}); + +pusher.connection.bind('connecting_in', function(delay: any) { + alert("I haven't been able to establish a connection for this feature. " + + "I will try again in " + delay + " seconds.") +}); + +pusher.connection.bind('state_change', function(states: any) { + // states = {previous: 'oldState', current: 'newState'} + $('div#status').text("Pusher's current state is " + states.current); +}); + +var connectionState: string = pusher.connection.state; + +// Accessing channels + +channel = pusher.channel(channelName); + +// Public channels + +channel = pusher.subscribe(channelName); + +pusher.unsubscribe(channelName); + +// Private channels + +var privateChannel = pusher.subscribe(privateChannelName); + +// Presence channels + +var presenceChannel: PresenceChannel = pusher.subscribe(presenceChannelName); + +var count: number = presenceChannel.members.count; + +presenceChannel.members.each(function(member: Pusher.UserInfo) { + var userId = member.id; + var userInfo = member.info; +}); + +var some_user_id: number; +var user = presenceChannel.members.get(some_user_id); + +var me = presenceChannel.members.me; + +pusher = new Pusher('app_key'); +presenceChannel = pusher.subscribe('presence-example'); +presenceChannel.bind('pusher:subscription_succeeded', function() { + var me = presenceChannel.members.me; + var userId = me.id; + var userInfo = me.info; +}); + +channel = pusher.subscribe('presence-meeting-11'); + +channel.bind('pusher:subscription_succeeded', function(members: Pusher.Members) { + // for example + update_member_count(members.count); + + members.each(function(member) { + // for example: + add_member(member.id, member.info); + }); +}); + +channel.bind('pusher:member_added', function(member: Pusher.UserInfo) { + // for example: + add_member(member.id, member.info); +}); + +channel.bind('pusher:member_removed', function(member: Pusher.UserInfo) { + // for example: + remove_member(member.id, member.info); +}); + +// Pusher Events + +channel.bind(eventName, callback); + +pusher = new Pusher('APP_KEY'); +channel = pusher.subscribe('APPL'); +channel.bind('new-price', + function(data: any) { + // add new price into the APPL widget + } +); + +var context = { title: 'Pusher' }; +var handler = function(){ + console.log('My name is ' + this.title); +}; +channel.bind('new-comment', handler, context); + +pusher.bind(eventName, callback); + +pusher = new Pusher('APP_KEY'); +var channel1 = pusher.subscribe('test_channel_1'); +var channel2 = pusher.subscribe('test_channel_2'); +var channel3 = pusher.subscribe('test_channel_3'); + +var eventName = 'new-comment'; +callback = function(data: any) { + // add comment into page +}; + +// listen for 'new-comment' event on channel 1, 2 and 3 +pusher.bind(eventName, callback); + +// Unbinding from Events + +channel.unbind(eventName, callback); + +pusher = new Pusher('APP_KEY'); +channel = pusher.subscribe('APPL'); +callback = function(data: any) {}; +channel.bind('new-price', callback); + +channel.unbind('new-price', callback); + +// Pusher channel events + +channel.bind('pusher:subscription_succeeded', function() { +}); + +pusher = new Pusher('APP_KEY'); +channel = pusher.subscribe('private-channel'); +channel.bind('pusher:subscription_error', function(status: number) { + if(status == 408 || status == 503){ + // retry? + } +}); + +// Triggering Client Events + +var triggered = channel.trigger(eventName, data); +pusher = new Pusher('YOUR_APP_KEY'); +channel = pusher.subscribe('private-channel'); +channel.bind('pusher:subscription_succeeded', function() { + var triggered = channel.trigger('client-someeventname', { your: data }); +}); + +// Best practice when sending client events + +var outputEl = document.getElementById('client_event_example_log'); +var state: any = { + currentX: 0, + currentY: 0, + lastX: undefined, + lastY: undefined +}; + +pusher = new Pusher("YOUR_APP_KEY"); +channel = pusher.subscribe("private-mousemoves"); + +// this method should be bound as a 'mousemove' event listener +document.body.addEventListener('mousemove', onMouseMove, false); +function onMouseMove(ev: any){ + ev = ev || window.event; + state.currentX = ev.pageX || ev.clientX; + state.currentY = ev.pageY || ev.clientY; +} + +setInterval(function(){ + if(state.currentX !== state.lastX || state.currentY !== state.lastY){ + state.lastX = state.currentX; + state.lastY = state.currentY; + + var text = document.createTextNode( + 'Triggering event due to state change: x: ' + state.currentX + ', y: ' + state.currentY + ); + outputEl.replaceChild( text, outputEl.firstChild ); + + channel.trigger("client-mouse-moved", {x:state.currentX, y: state.currentY}); + } +}, 300); // send every 300 milliseconds if position has changed + diff --git a/pusher-js/pusher-js.d.ts b/pusher-js/pusher-js.d.ts index 393cba720..9306faa8f 100644 --- a/pusher-js/pusher-js.d.ts +++ b/pusher-js/pusher-js.d.ts @@ -18,6 +18,14 @@ declare module "pusher-js" { allChannels(): Channel[]; bind(eventName: string, callback: Function): Pusher; bind_all(callback: Function): Pusher; + disconnect(): void; + key: string; + config: Config; //TODO: add GlobalConfig typings + channels: any; //TODO: Type this + global_emitter: EventsDispatcher; + sessionId: number; + timeline: any; //TODO: Type this + connection: ConnectionManager; } interface Config { @@ -103,15 +111,117 @@ declare module "pusher-js" { headers?: { [key: string]: any }; } - interface Channel { - bind(eventName: string, callback: Function, context?: any): Channel; - bind_all(callback: Function): Channel; - unbind(eventName?: string, callback?: Function, context?: any): Channel; - unbind_all(eventName?: string, callback?: Function): Channel; - trigger(eventName: string, data?: any): any; + interface GenericEventsDispatcher extends EventsDispatcher { + bind(eventName: string, callback: Function, context?: any): Self; + bind_all(callback: Function): Self; + unbind(eventName?: string, callback?: Function, context?: any): Self; + unbind_all(eventName?: string, callback?: Function): Self; + emit(eventName: string, data?: any): Self; + } + + interface Channel extends GenericEventsDispatcher { + /** Triggers an event */ + trigger(eventName: string, data?: any): boolean; pusher: Pusher; name: string; subscribed: boolean; + /** + * Authenticates the connection as a member of the channel. + * @param {String} socketId + * @param {Function} callback + */ + authorize(socketId: string, callback: (data: any) => void): void; + } + + interface EventsDispatcher { + bind(eventName: string, callback: Function, context?: any): EventsDispatcher; + bind_all(callback: Function): EventsDispatcher; + unbind(eventName?: string, callback?: Function, context?: any): EventsDispatcher; + unbind_all(eventName?: string, callback?: Function): EventsDispatcher; + emit(eventName: string, data?: any): EventsDispatcher; + } + + interface ConnectionManager extends GenericEventsDispatcher { + key: string; + options: any; //TODO: Timeline.js + state: string; + connection: any; //TODO: Type this + encrypted: boolean; + timeline: any; //TODO: Type this + connectionCallbacks: { + message: (message: string) => void; + ping: () => void; + activity: () => void; + error: (error: any) => void; + closed: () => void; + }; + errorCallbacks: { + ssl_only: () => void; + refused: () => void; + backoff: () => void; + retry: () => void; + }; + handshakeCallbacks: { + ssl_only: () => void; + refused: () => void; + backoff: () => void; + retry: () => void; + connected: (handshake: any) => void; //TODO: Type this + }; + /** + * Establishes a connection to Pusher. + * + * Does nothing when connection is already established. See top-level doc + * to find events emitted on connection attempts. + */ + connect(): void; + /** + * Sends raw data. + * @param {String} data + */ + send(data: string): boolean; + /** Sends an event. + * + * @param {String} name + * @param {String} data + * @param {String} [channel] + * @returns {Boolean} whether message was sent or not + */ + send_event(name: string, data: string, channel: string): boolean; + /** Closes the connection. */ + disconnect(): void; + isEncrypted(): boolean; + } + + interface PresenceChannel extends Channel { + members: Members; + } + + interface Members { + /** + * Returns member's info for given id. + * + * Resulting object containts two fields - id and info. + * + * @param {Number} id + * @return {Object} member's info or null + */ + get(id: number): T; + /** + * Calls back for each member in unspecified order. + * + * @param {Function} callback + */ + each(callback: (member: any) => void): void; + members: { [id: number]: UserInfo }; + count: number; + myID: number; + me: UserInfo; + } + + interface UserInfo { + id: number; + info: T; } } @@ -119,4 +229,3 @@ declare module "pusher-js" { export = pusher; } -