New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

connect.io

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

connect.io - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

dist/chrome-connect.common.js

17

libs/client.js

@@ -1,6 +0,5 @@

var Port = require('./port')
var runtime = require('./utils/chrome-runtime')
var id = runtime.id
import Port from './port'
import runtime from './utils/chrome-runtime'
module.exports = createClient
const { id } = runtime

@@ -16,3 +15,3 @@ /**

*/
function createClient (eIdOrTabId, options) {
export default function (eIdOrTabId, options) {
// createClient(options)

@@ -30,10 +29,10 @@ if (typeof eIdOrTabId === 'object') {

var portNamespace = options.namespace || 'default'
const portNamespace = options.namespace || 'default'
// 把参数放在 name 里传到服务端
var params = JSON.stringify({
const params = JSON.stringify({
_namespace: portNamespace
})
var chromePort
let chromePort
switch (typeof eIdOrTabId) {

@@ -55,5 +54,5 @@ case 'string': // 扩展 id 是字符串

var port = new Port(chromePort)
const port = new Port(chromePort)
port.namespace = portNamespace
return port
}

@@ -1,5 +0,9 @@

module.exports = {
createClient: require('./client'),
createServer: require('./server'),
send: require('./send')
import createClient from './client'
import createServer from './server'
import send from './send'
export {
createClient,
createServer,
send
}

@@ -1,115 +0,108 @@

var TinyEmitter = require('tiny-emitter')
var uuid = require('./utils/uuid')
var noop = require('./utils/noop')
import TinyEmitter from 'tiny-emitter'
module.exports = Port
import uuid from './utils/uuid'
import noop from './utils/noop'
/**
* 对 chrome 的 Port 类型的包装
* @param {chrome.runtime.Port} port
*/
function Port (port) {
TinyEmitter.call(this)
this.disconnected = false
export default class extends TinyEmitter {
constructor (port) {
super()
this.disconnected = false
/**
* 一个 hash map,键是消息的 uuid,值是一个函数,用于保存那些待响应的函数
* @type {{}}
*/
var waitingResponseMsg = this._waiting = {}
this.port = port
/**
* 一个 hash map,键是消息的 uuid,值是一个函数,用于保存那些待响应的函数
* @type {{}}
*/
const waitingResponseMsg = this._waiting = {}
this.port = port
var that = this
port.onMessage.addListener(function (msg) {
var id = msg.id
port.onMessage.addListener(msg => {
const { id } = msg
// 如果在字典里找到了对应 id 的回调函数,那么说明这个消息是由本地端口发送的并有回调函数,
// 否则说明这个消息是由远程端口发送的,要把 id 传回去,让远程端口定位到它的回调函数;此时这个消息是没有 name 的
var cb = waitingResponseMsg[id]
if (cb) {
delete waitingResponseMsg[id]
cb(msg.error, msg.response)
} else {
if (id) {
new Promise(function (resolve, reject) {
that.emit(msg.name, msg.data, resolve, reject)
}).then(
function (response) { port.postMessage({ id: id, response: response }) },
function (error) { port.postMessage({ id: id, error: error }) }
)
// 如果在字典里找到了对应 id 的回调函数,那么说明这个消息是由本地端口发送的并有回调函数,
// 否则说明这个消息是由远程端口发送的,要把 id 传回去,让远程端口定位到它的回调函数;此时这个消息是没有 name 的
const cb = waitingResponseMsg[id]
if (cb) {
delete waitingResponseMsg[id]
cb(msg.error, msg.response)
} else {
that.emit(msg.name, msg.data, noop, noop)
if (id) {
new Promise((resolve, reject) => {
this.emit(msg.name, msg.data, resolve, reject)
}).then(
response => { port.postMessage({ id, response }) },
error => { port.postMessage({ id, error }) }
)
} else {
this.emit(msg.name, msg.data, noop, noop)
}
}
}
})
// 进入这个回调说明连接是被远程端口断开的
port.onDisconnect.addListener(function () { that.emit('disconnect', true) })
this.once('disconnect',
/**
* 当连接断开时,告诉所有等待响应的消息一个错误
* @param {Boolean} isByOtherSide - 连接是否是被另一端断开的
*/
function (isByOtherSide) {
var error = new Error('Connection has been disconnected by ' + (isByOtherSide ? 'the other side' : 'yourself') + '.')
that.disconnected = true
that.disconnect = noop
that.send = function () {
throw error
}
for (var key in waitingResponseMsg) {
waitingResponseMsg[key](error)
delete waitingResponseMsg[key]
}
})
}
var pp = Port.prototype = Object.create(TinyEmitter.prototype)
// 进入这个回调说明连接是被远程端口断开的
port.onDisconnect.addListener(() => { this.emit('disconnect', true) })
/**
* 发送消息到另一端
* @param {String} name - 消息名称
* @param {*} [data] 数据
* @param {Boolean} [needResponse] - 如果是 true,则此方法返回一个 Promise,当得到相应时会被 resolve 或 reject。
*
* @example
* send('name', 'data', true)
* send('name', true) - 这种情况下,data 为 undefined,needResponse 为 true
* send('name', 'data')
* send('name')
*/
pp.send = function (name, data, needResponse) {
if (data === true && arguments.length === 2) {
data = undefined
needResponse = true
this.once('disconnect',
/**
* 当连接断开时,告诉所有等待响应的消息一个错误
* @param {Boolean} isByOtherSide - 连接是否是被另一端断开的
*/
isByOtherSide => {
const error = new Error('Connection has been disconnected by ' + (isByOtherSide ? 'the other side' : 'yourself') + '.')
this.disconnected = true
this.disconnect = noop
this.send = function () {
throw error
}
for (let key in waitingResponseMsg) {
waitingResponseMsg[key](error)
delete waitingResponseMsg[key]
}
})
}
var msg = {
name: name,
data: data
}
var p
if (needResponse) {
var that = this
p = new Promise(function (resolve, reject) {
that._waiting[msg.id = uuid()] = function (error, response) {
if (error) {
reject(error)
} else {
resolve(response)
/**
* 发送消息到另一端
* @param {String} name - 消息名称
* @param {*} [data] 数据
* @param {Boolean} [needResponse] - 如果是 true,则此方法返回一个 Promise,当得到相应时会被 resolve 或 reject。
*
* @example
* send('name', 'data', true)
* send('name', true) - 这种情况下,data 为 undefined,needResponse 为 true
* send('name', 'data')
* send('name')
*/
send (name, data, needResponse) {
if (data === true && arguments.length === 2) {
data = undefined
needResponse = true
}
const msg = {
name: name,
data: data
}
let p
if (needResponse) {
p = new Promise((resolve, reject) => {
this._waiting[msg.id = uuid()] = function (error, response) {
if (error) {
reject(error)
} else {
resolve(response)
}
}
}
})
})
}
this.port.postMessage(msg)
return p
}
this.port.postMessage(msg)
return p
}
/**
* 主动断开与远程端口的连接,
* 此时不会触发 port.onDisconnect 事件。
*/
pp.disconnect = function () {
this.port.disconnect()
this.emit('disconnect', false)
/**
* 主动断开与远程端口的连接,
* 此时不会触发 port.onDisconnect 事件。
*/
disconnect () {
this.port.disconnect()
this.emit('disconnect', false)
}
}

@@ -116,0 +109,0 @@

@@ -1,5 +0,3 @@

var createClient = require('./client')
import createClient from './client'
module.exports = send
/**

@@ -19,12 +17,12 @@ * 发送一次性消息

*/
function send (options) {
var client = createClient(options.id, { frameId: options.frameId, namespace: options.namespace })
var promise = client.send(options.name, options.data, options.needResponse)
export default function (options) {
const client = createClient(options.id, { frameId: options.frameId, namespace: options.namespace })
const promise = client.send(options.name, options.data, options.needResponse)
if (promise) {
return promise.then(
function (response) {
response => {
client.disconnect()
return response
},
function (error) {
error => {
client.disconnect()

@@ -31,0 +29,0 @@ return Promise.reject(error)

@@ -1,26 +0,14 @@

var TinyEmitter = require('tiny-emitter')
var noop = require('./utils/noop')
var Port = require('./port')
var runtime = require('./utils/chrome-runtime')
import TinyEmitter from 'tiny-emitter'
import noop from './utils/noop'
import Port from './port'
import runtime from './utils/chrome-runtime'
module.exports = createServer
// namespace 到 server 对象的映射表
var serversMap = {}
function createServer (namespace) {
if (!namespace) namespace = 'default'
var existServer = serversMap[namespace]
if (existServer) return existServer
return (serversMap[namespace] = new Server(namespace))
}
// 第一次调用 new Server() 的时候才添加这些事件监听
var initListener = function () {
let initListener = function () {
initListener = noop
var onConnect = runtime.onConnect
var onConnectExternal = runtime.onConnectExternal
const { onConnect, onConnectExternal } = runtime
if (onConnect) {
onConnect.addListener(function (chromePort) {
onConnect.addListener(chromePort => {
initServerPort(chromePort, false)

@@ -31,3 +19,3 @@ })

if (onConnectExternal) {
onConnectExternal.addListener(function (chromePort) {
onConnectExternal.addListener(chromePort => {
initServerPort(chromePort, true)

@@ -38,25 +26,34 @@ })

function Server (namespace) {
initListener()
TinyEmitter.call(this)
this.namespace = namespace
class Server extends TinyEmitter {
constructor (namespace) {
super()
initListener()
this.namespace = namespace
/**
* 连接到此服务端的端口的集合
* @type {Port[]}
*/
this.ports = []
}
/**
* 连接到此服务端的端口的集合
* @type {Port[]}
* 发送消息到此服务器下的所有客户端
* @param {String} name
* @param {*} [data]
*/
this.ports = []
send (name, data) {
this.ports.forEach(clientPort => {
clientPort.send(name, data)
})
}
}
var sp = Server.prototype = Object.create(TinyEmitter.prototype)
// namespace 到 server 对象的映射表
const serversMap = {}
/**
* 发送消息到此服务器下的所有客户端
* @param {String} name
* @param {*} [data]
*/
sp.send = function (name, data) {
this.ports.forEach(function (clientPort) {
clientPort.send(name, data)
})
export default function (namespace = 'default') {
const existServer = serversMap[namespace]
if (existServer) return existServer
return (serversMap[namespace] = new Server(namespace))
}

@@ -72,3 +69,3 @@

// 若没有则说明这个客户端不是 client 发来的
var options
let options

@@ -81,9 +78,7 @@ try {

var _namespace = options._namespace
if (!_namespace) {
return
}
const { _namespace } = options
if (!_namespace) return
// 如果此 client 尝试连接的服务端没有,则断开连接
var server = serversMap[_namespace]
const server = serversMap[_namespace]
if (!server) {

@@ -95,3 +90,3 @@ chromePort.disconnect()

// 将此端口加入到服务端的端口列表中
var ports = server.ports
const { ports } = server
const port = new Port(chromePort)

@@ -109,3 +104,3 @@

port.broadcast = function (name, data) {
ports.forEach(function (clientPort) {
ports.forEach(clientPort => {
if (clientPort !== port) {

@@ -112,0 +107,0 @@ clientPort.send(name, data)

@@ -1,6 +0,1 @@

var chrome = window.chrome
var runtime = chrome && chrome.runtime
if (!runtime) throw new Error('You\'re not in Google Chrome.')
module.exports = runtime || null
export default chrome.runtime

@@ -1,1 +0,1 @@

module.exports = function () {}
export default function () {}

@@ -1,5 +0,5 @@

var id = 0
let id = 0
module.exports = function () {
export default function () {
return String(id++)
}
{
"name": "connect.io",
"version": "2.0.0",
"version": "3.0.0",
"description": "Real-time bidirectional event-based and Promise friendly communication in Chrome extensions or Apps inspired by Socket.IO. ",
"scripts": {
"dev": "webpack --watch",
"build": "webpack -p",
"test": "karma start",
"lint": "eslint --ignore-pattern '/dist/' --ignore-pattern '/coverage/' \"**/*.js\"",
"prepublish": "npm run build"
"build": "node build/build.js",
"lint": "eslint --ignore-pattern '/dist/' --ignore-pattern '/coverage/' '**/*.js'",
"prepublish": "yarn run build"
},
"main": "./libs/index.js",
"main": "dist/chrome-connect.common.js",
"module": "dist/chrome-connect.esm.js",
"unpkg": "dist/chrome-connect.js",
"keywords": [

@@ -21,4 +22,4 @@ "chrome",

"bidirectional",
"extension",
"app"
"chrome extension",
"chrome app"
],

@@ -30,26 +31,27 @@ "files": [

"dependencies": {
"tiny-emitter": "1.1.0"
"tiny-emitter": "^2.0.0"
},
"devDependencies": {
"babel-core": "6.18.0",
"babel-loader": "6.2.5",
"babel-preset-es2015": "6.18.0",
"chrome-env": "0.1.0",
"es6-promise": "4.0.5",
"eslint": "3.8.1",
"eslint-config-standard": "6.2.0",
"eslint-plugin-promise": "3.3.0",
"eslint-plugin-standard": "2.0.1",
"istanbul-instrumenter-loader": "1.0.0",
"jasmine-core": "2.5.2",
"karma": "1.3.0",
"karma-chrome-launcher": "2.0.0",
"karma-coverage": "1.1.1",
"karma-coveralls": "1.1.2",
"karma-jasmine": "1.0.2",
"karma-phantomjs-launcher": "1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "1.8.0",
"phantomjs-prebuilt": "2.1.13",
"webpack": "1.13.2"
"es6-promise": "^4.0.5",
"eslint": "^4.0.0",
"eslint-config-standard": "^10.2.0",
"eslint-plugin-html": "^3.0.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^5.0.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"jasmine-core": "^2.5.2",
"karma": "^1.3.0",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-coveralls": "^1.1.2",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-rollup-preprocessor": "^4.0.0",
"phantomjs-prebuilt": "^2.1.13",
"rollup": "^0.43.0",
"rollup-plugin-buble": "^0.15.0",
"rollup-plugin-istanbul": "^1.1.0",
"uglify-js": "^3.0.23"
},

@@ -56,0 +58,0 @@ "repository": {

@@ -6,3 +6,3 @@ # connect.io

[![dependencies Status](https://img.shields.io/david/Selection-Translator/connect.io.svg?style=flat-square)](https://david-dm.org/Selection-Translator/connect.io)
[![devDependencies Status](https://img.shields.io/david/dev/Selection-Translator/connect.io.svg?style=flat-square)](https://david-dm.org/Selection-Translator/connect.io#info=devDependencies)
[![devDependencies Status](https://img.shields.io/david/dev/Selection-Translator/connect.io.svg?style=flat-square)](https://david-dm.org/Selection-Translator/connect.io?type=dev)
[![NPM Version](https://img.shields.io/npm/v/connect.io.svg?style=flat-square)](https://www.npmjs.com/package/connect.io)

@@ -14,143 +14,258 @@

### With <script> tag
### Use with Webpack
Download script: https://unpkg.com/connect.io/dist/connect.js
If you build your project with Webpack, you can install connect.io via npm:
Then in your html:
```
npm install connect.io
```
Then you can import it in your project:
```js
// es6
import { createClient, createServer, send } from 'connect.io'
// commonjs
const { createClient, createServer, send } = require('connect.io')
```
### Use with <script>
Download chrome-connect.js from [unpkg](https://unpkg.com/connect.io/dist/chrome-connect.js)([min version](https://unpkg.com/connect.io/dist/chrome-connect.min.js)).
Then reference it in your html:
```html
<script src="path/to/connect.js"></script>
<script>chromeConnect.send(...)</script>
<script src="path/to/chrome-connect.js"></script>
<!-- now you will get a global variable named chromeConnect -->
<script>
var createClient = chromeConnect.createClient
var createServer = chromeConnect.createServer
var send = chromeConnect.send
</script>
```
### With webpack
## Usage
Install via NPM:
### Send message from content script to background
First, create a server in background page(or other pages like popup, options):
```js
import { createServer } from 'connect.io'
const server = createServer()
```
npm i -S connect.io
Second, listen `connect` event on server:
```js
server.on('connect', client => {
// client is a Client object
})
```
Then:
Finally, create a client in content script:
```js
import chromeConnect from 'connect.io'
chromeConnect.send(...)
import { createClient } from 'connect.io'
// client is an Client object
const client = createClient()
```
## Usage
For more information about the `Client` object please read the API below.
background.js:
### Send message from background to content script
Only different with the above steps is: when you create client in background, you must specify the tab id in `createClient`.
For example, in your background:
```js
const server = chromeConnect.createServer('optional namespace, default is "default"')
server.on('connect', client => {
import { createClient } from 'connect.io'
if (client.external && client.port.sender.url === YourBlackList) {
client.disconnect()
return
}
const clientInBackground = createClient(1001) // the tab id you want to connect
```
// Only send message to this connection client.
// If you want get response, pass "true" as the last argument,
// then "client.send()" will return a promise.
// Otherwise, "client.send()" just return undefined.
client
.send('welcome', 'hello world',true)
.then(
response => console.log(response), // print "Thanks!"
error => console.log(error) // print "I'm not happy."
)
### Using namespace
// Note: if you just want send a "true" to the other side and don't want response,
// You must do:
client.send('send true and do not need response', true, false)
Server can optional has a namespace:
// I recommend you use 1 to instead of true, so you can omit the last argument:
client.send('use 1 to instead of true', 1)
```js
import { createServer } from 'connect.io'
// then in other side:
//client.on('use 1 to instead of true', data => {
// console.log(data) // 1
// if(data) {
// //...
// }
//})
const serverTweets = createServer('tweets')
// Sending a message to everyone else except for the connection that starts it.
client.broadcast('join', 'new client joined.')
// Sending response to client
client.on('report clients number', (data, resolve, reject) => {
resolve(server.ports.length)
serverTweets.on('connect', client => {
client.on('tweet', tween => {
postTweet(tween)
})
})
// handle connection disconnect on Server
client.once('disconnect', isOtherSide => {
// Sending message to every connection.
server.send(isOtherSide ? 'Someone out by himself.' : 'I knock it out.')
const serverNotification = createServer('notification')
serverNotification.on('connect', client => {
client.on('notice', () => {
showNotification()
})
});
})
```
content-scripts.js:
You can connect to different server in client:
```js
// sending one-time message
chromeConnect.send({
// specify extension/app or tab id. Default value is chrome.runtime.id
id: '', // Number or String
import { createClient } from 'connect.io'
frameId: 0, // see https://developer.chrome.com/extensions/tabs#method-connect
const clientTweets = createClient({
namespace: 'tweets'
})
namespace:'default',
clientTweets.send('tweet', 'connect.io is awesome')
name: 'your msg name',
data: { your:'data' },
needResponse: true // if true, send() will return a Promise, otherwise it just return undefined.
}).then(
// ....
)
const clientNotification = createClient({
namespace: 'notification'
})
// long-lived connections
const client = chromeConnect.createClient('optional extensions/apps or tab id. default value is chrome.runtime.id',{
frameId:0, // only used when first argument is tabId
namespace: ''
clientNotification.send('notice')
```
### Get response from server
You can send response from server to the client. For example:
```js
// in server
import { createServer } from 'connect.io'
const server = createServer()
server.on('connect', client => {
client.on('Do I have enough money?', (data, resolve, reject) => {
if (data > 100) {
resolve('Yes you do.')
} else {
reject('You need more money.')
}
})
})
```
client.on('welcome', (data, resolve, reject) => {
console.log(data) // 'hello world'
// if you want, you can send a response to Server as resolved.
resolve('Thanks!')
// or you can send an error as a rejection.
reject('I\'m not happy.')
```js
// in client
import { createClient } from 'connect.io'
const client = createClient()
// pass true as the last params to get response
client.send('Do I have enough money?', 50, true).catch(msg => {
console.log(msg) // 'You need more money.'
})
client.on('join', function(data) {
console.log(data) // "new client joined."
client.send('Do I have enough money?', 10000, true).then(msg => {
console.log(msg) // 'Yes you do.'
})
```
// get Server response.
client
.send('report clients number', true)
.then(
res => console.log(res), // 1
error => console.log(error)
)
### Send one-time message
client.on('Someone out', () => {
// ...
})
If you want to send one-time message and don't want to create a client, you can use `send` method:
// handle connection disconnect on Client
client.once('disconnect', isOtherSide => {
console.log('Connection disconnected by ', isOtherSide ? 'the other side' : 'myself', '.')
```js
import { send } from 'connect.io'
send({
name: 'Do I have enough money?',
data: 10000,
needResponse: true
}).then(msg => {
console.log(msg) // 'Yes you do.'
})
```
// disconnect the connection.
client.disconnect()
## API
### createServer([namespace])
Return a `Server` object.
Note: same namespace get the same `Server` object.
```js
import { createServer } from 'connect.io'
createServer() === createServer() // true
createServer('namespace') === createServer('namespace') // true
createServer('foo') === createServer('bar') // false
```
### Server
Create from `createServer` method.
#### Server#send(name[, data])
Send message to all clients that connect to this server.
#### Server#on(event, handler)
Listen event. For now there is only one event: `connect`.
### createClient([id, options])
Return a `Client` object.
If you want to connect to content script from background, then `id` is necessary and must be a tab id.
`options` has these property:
- `namespace`: which server you want connect
- `frameId`: if you are connect to content script from background, you can specify a [frameId](https://developer.chrome.com/extensions/runtime#property-MessageSender-frameId) to connect only this frame.
### Client
Create from `createClient`, or provided in `server.on('connect')` event.
#### Client#port
The native chrome [Port](https://developer.chrome.com/extensions/runtime#type-Port) object.
#### Client#external
If this client is connect from webpage or other extension, then this property is `true`.
#### Client#send(name[, data, needResponse])
Send message to server or client.
#### Client#on(name, handler(data, resolve, reject))
Receive message from server or client. Use `resolve` or `reject` method to response this message to server or client.
#### Client#broadcast(name[, data])
Note: this method only exist in server.
Sending a message to everyone else except for the connection that starts it.
#### Client#disconnect()
Disconnect the connection.
### send(options)
Send one-time message.
The `options` has these property:
- `id`: optional. If you want to connect to content script from background, then `id` is necessary and must be a tab id.
- `frameId`: optional. See `createClient([id, options])` API.
- `namespace`: optional. See `createClient([id, options])` API.
- `name`: the message name.
- `data`: the data you want send.
- `needResponse`: if you need response, then set this to `true`
## License
MIT
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc