Tracking de l'application VApp (IHM du jeu)
This commit is contained in:
39
VApp/node_modules/mqtt/src/bin/mqtt.ts
generated
vendored
Normal file
39
VApp/node_modules/mqtt/src/bin/mqtt.ts
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-2015 MQTT.js contributors.
|
||||
* Copyright (c) 2011-2014 Adam Rudd.
|
||||
*
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
import path from 'path'
|
||||
import Commist from 'commist'
|
||||
import help from 'help-me'
|
||||
import publish from './pub'
|
||||
import subscribe from './sub'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const version = require('../../package.json').version
|
||||
|
||||
const helpMe = help({
|
||||
dir: path.join(__dirname, '../../', 'help'),
|
||||
ext: '.txt',
|
||||
})
|
||||
|
||||
const commist = Commist()
|
||||
|
||||
commist.register('publish', publish)
|
||||
commist.register('pub', publish)
|
||||
|
||||
commist.register('subscribe', subscribe)
|
||||
commist.register('sub', subscribe)
|
||||
|
||||
commist.register('version', () => {
|
||||
console.log('MQTT.js version:', version)
|
||||
})
|
||||
commist.register('help', helpMe.toStdout)
|
||||
|
||||
if (commist.parse(process.argv.slice(2)) !== null) {
|
||||
console.log('No such command:', process.argv[2], '\n')
|
||||
helpMe.toStdout()
|
||||
}
|
174
VApp/node_modules/mqtt/src/bin/pub.ts
generated
vendored
Normal file
174
VApp/node_modules/mqtt/src/bin/pub.ts
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Writable } from 'readable-stream'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import concat from 'concat-stream'
|
||||
import help from 'help-me'
|
||||
|
||||
import minimist, { ParsedArgs } from 'minimist'
|
||||
import split2 from 'split2'
|
||||
import { connect } from '../mqtt'
|
||||
import { IClientOptions, IClientPublishOptions } from 'src/lib/client'
|
||||
import { pipeline } from 'stream'
|
||||
|
||||
const helpMe = help({
|
||||
dir: path.join(__dirname, '../../', 'help'),
|
||||
})
|
||||
|
||||
function send(args: ParsedArgs) {
|
||||
const client = connect(args as IClientOptions)
|
||||
client.on('connect', () => {
|
||||
client.publish(
|
||||
args.topic,
|
||||
args.message,
|
||||
args as IClientPublishOptions,
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.warn(err)
|
||||
}
|
||||
client.end()
|
||||
},
|
||||
)
|
||||
})
|
||||
client.on('error', (err) => {
|
||||
console.warn(err)
|
||||
client.end()
|
||||
})
|
||||
}
|
||||
|
||||
function multisend(args: ParsedArgs) {
|
||||
const client = connect(args as IClientOptions)
|
||||
const sender = new Writable({
|
||||
objectMode: true,
|
||||
})
|
||||
sender._write = (line, enc, cb) => {
|
||||
client.publish(
|
||||
args.topic,
|
||||
line.trim(),
|
||||
args as IClientPublishOptions,
|
||||
cb,
|
||||
)
|
||||
}
|
||||
|
||||
client.on('connect', () => {
|
||||
pipeline(process.stdin, split2(), sender, (err) => {
|
||||
client.end()
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default function start(args: string[]) {
|
||||
const parsedArgs = minimist(args, {
|
||||
string: [
|
||||
'hostname',
|
||||
'username',
|
||||
'password',
|
||||
'key',
|
||||
'cert',
|
||||
'ca',
|
||||
'message',
|
||||
'clientId',
|
||||
'i',
|
||||
'id',
|
||||
],
|
||||
boolean: ['stdin', 'retain', 'help', 'insecure', 'multiline'],
|
||||
alias: {
|
||||
port: 'p',
|
||||
hostname: ['h', 'host'],
|
||||
topic: 't',
|
||||
message: 'm',
|
||||
qos: 'q',
|
||||
clientId: ['i', 'id'],
|
||||
retain: 'r',
|
||||
username: 'u',
|
||||
password: 'P',
|
||||
stdin: 's',
|
||||
multiline: 'M',
|
||||
protocol: ['C', 'l'],
|
||||
help: 'H',
|
||||
ca: 'cafile',
|
||||
},
|
||||
default: {
|
||||
host: 'localhost',
|
||||
qos: 0,
|
||||
retain: false,
|
||||
topic: '',
|
||||
message: '',
|
||||
},
|
||||
})
|
||||
|
||||
if (parsedArgs.help) {
|
||||
return helpMe.toStdout('publish')
|
||||
}
|
||||
|
||||
if (parsedArgs.key) {
|
||||
parsedArgs.key = fs.readFileSync(parsedArgs.key)
|
||||
}
|
||||
|
||||
if (parsedArgs.cert) {
|
||||
parsedArgs.cert = fs.readFileSync(parsedArgs.cert)
|
||||
}
|
||||
|
||||
if (parsedArgs.ca) {
|
||||
parsedArgs.ca = fs.readFileSync(parsedArgs.ca)
|
||||
}
|
||||
|
||||
if (parsedArgs.key && parsedArgs.cert && !parsedArgs.protocol) {
|
||||
parsedArgs.protocol = 'mqtts'
|
||||
}
|
||||
|
||||
if (parsedArgs.port) {
|
||||
if (typeof parsedArgs.port !== 'number') {
|
||||
console.warn(
|
||||
"# Port: number expected, '%s' was given.",
|
||||
typeof parsedArgs.port,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedArgs['will-topic']) {
|
||||
parsedArgs.will = {}
|
||||
parsedArgs.will.topic = parsedArgs['will-topic']
|
||||
parsedArgs.will.payload = parsedArgs['will-message']
|
||||
parsedArgs.will.qos = parsedArgs['will-qos']
|
||||
parsedArgs.will.retain = parsedArgs['will-retain']
|
||||
}
|
||||
|
||||
if (parsedArgs.insecure) {
|
||||
parsedArgs.rejectUnauthorized = false
|
||||
}
|
||||
|
||||
parsedArgs.topic = (parsedArgs.topic || parsedArgs._.shift())?.toString()
|
||||
parsedArgs.message = (
|
||||
parsedArgs.message || parsedArgs._.shift()
|
||||
)?.toString()
|
||||
|
||||
if (!parsedArgs.topic) {
|
||||
console.error('missing topic\n')
|
||||
return helpMe.toStdout('publish')
|
||||
}
|
||||
|
||||
if (parsedArgs.stdin) {
|
||||
if (parsedArgs.multiline) {
|
||||
multisend(parsedArgs)
|
||||
} else {
|
||||
process.stdin.pipe(
|
||||
concat((data) => {
|
||||
parsedArgs.message = data
|
||||
send(parsedArgs)
|
||||
}),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
send(parsedArgs)
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
start(process.argv.slice(2))
|
||||
}
|
146
VApp/node_modules/mqtt/src/bin/sub.ts
generated
vendored
Normal file
146
VApp/node_modules/mqtt/src/bin/sub.ts
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import minimist from 'minimist'
|
||||
import help from 'help-me'
|
||||
import { connect } from '../mqtt'
|
||||
import { IClientOptions } from 'src/lib/client'
|
||||
|
||||
const helpMe = help({
|
||||
dir: path.join(__dirname, '../../', 'help'),
|
||||
})
|
||||
|
||||
export default function start(args: string[]) {
|
||||
const parsedArgs = minimist(args, {
|
||||
string: [
|
||||
'hostname',
|
||||
'username',
|
||||
'password',
|
||||
'key',
|
||||
'cert',
|
||||
'ca',
|
||||
'clientId',
|
||||
'i',
|
||||
'id',
|
||||
],
|
||||
boolean: ['stdin', 'help', 'clean', 'insecure'],
|
||||
alias: {
|
||||
port: 'p',
|
||||
hostname: ['h', 'host'],
|
||||
topic: 't',
|
||||
qos: 'q',
|
||||
clean: 'c',
|
||||
keepalive: 'k',
|
||||
clientId: ['i', 'id'],
|
||||
username: 'u',
|
||||
password: 'P',
|
||||
protocol: ['C', 'l'],
|
||||
verbose: 'v',
|
||||
help: '-H',
|
||||
ca: 'cafile',
|
||||
},
|
||||
default: {
|
||||
host: 'localhost',
|
||||
qos: 0,
|
||||
retain: false,
|
||||
clean: true,
|
||||
keepAlive: 30, // 30 sec
|
||||
},
|
||||
})
|
||||
|
||||
if (parsedArgs.help) {
|
||||
return helpMe.toStdout('subscribe')
|
||||
}
|
||||
|
||||
parsedArgs.topic = parsedArgs.topic || parsedArgs._.shift()
|
||||
|
||||
if (!parsedArgs.topic) {
|
||||
console.error('missing topic\n')
|
||||
return helpMe.toStdout('subscribe')
|
||||
}
|
||||
|
||||
if (parsedArgs.key) {
|
||||
parsedArgs.key = fs.readFileSync(parsedArgs.key)
|
||||
}
|
||||
|
||||
if (parsedArgs.cert) {
|
||||
parsedArgs.cert = fs.readFileSync(parsedArgs.cert)
|
||||
}
|
||||
|
||||
if (parsedArgs.ca) {
|
||||
parsedArgs.ca = fs.readFileSync(parsedArgs.ca)
|
||||
}
|
||||
|
||||
if (parsedArgs.key && parsedArgs.cert && !parsedArgs.protocol) {
|
||||
parsedArgs.protocol = 'mqtts'
|
||||
}
|
||||
|
||||
if (parsedArgs.insecure) {
|
||||
parsedArgs.rejectUnauthorized = false
|
||||
}
|
||||
|
||||
if (parsedArgs.port) {
|
||||
if (typeof parsedArgs.port !== 'number') {
|
||||
console.warn(
|
||||
"# Port: number expected, '%s' was given.",
|
||||
typeof parsedArgs.port,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedArgs['will-topic']) {
|
||||
parsedArgs.will = {}
|
||||
parsedArgs.will.topic = parsedArgs['will-topic']
|
||||
parsedArgs.will.payload = parsedArgs['will-message']
|
||||
parsedArgs.will.qos = parsedArgs['will-qos']
|
||||
parsedArgs.will.retain = parsedArgs['will-retain']
|
||||
}
|
||||
|
||||
parsedArgs.keepAlive = parsedArgs['keep-alive']
|
||||
|
||||
const client = connect(parsedArgs as IClientOptions)
|
||||
|
||||
client.on('connect', () => {
|
||||
client.subscribe(
|
||||
parsedArgs.topic,
|
||||
{ qos: parsedArgs.qos },
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
result.forEach((sub) => {
|
||||
if (sub.qos > 2) {
|
||||
console.error(
|
||||
'subscription negated to',
|
||||
sub.topic,
|
||||
'with code',
|
||||
sub.qos,
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
client.on('message', (topic, payload) => {
|
||||
if (parsedArgs.verbose) {
|
||||
console.log(topic, payload.toString())
|
||||
} else {
|
||||
console.log(payload.toString())
|
||||
}
|
||||
})
|
||||
|
||||
client.on('error', (err) => {
|
||||
console.warn(err)
|
||||
client.end()
|
||||
})
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
start(process.argv.slice(2))
|
||||
}
|
4
VApp/node_modules/mqtt/src/index.ts
generated
vendored
Normal file
4
VApp/node_modules/mqtt/src/index.ts
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import * as mqtt from './mqtt'
|
||||
|
||||
export default mqtt
|
||||
export * from './mqtt'
|
105
VApp/node_modules/mqtt/src/lib/BufferedDuplex.ts
generated
vendored
Normal file
105
VApp/node_modules/mqtt/src/lib/BufferedDuplex.ts
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
import { Duplex, Transform } from 'readable-stream'
|
||||
import { IClientOptions } from './client'
|
||||
|
||||
/**
|
||||
* Utils writev function for browser, ensure to write Buffers to socket (convert strings).
|
||||
*/
|
||||
export function writev(
|
||||
chunks: { chunk: any; encoding: string }[],
|
||||
cb: (err?: Error) => void,
|
||||
) {
|
||||
const buffers = new Array(chunks.length)
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
if (typeof chunks[i].chunk === 'string') {
|
||||
buffers[i] = Buffer.from(chunks[i].chunk, 'utf8')
|
||||
} else {
|
||||
buffers[i] = chunks[i].chunk
|
||||
}
|
||||
}
|
||||
|
||||
this._write(Buffer.concat(buffers), 'binary', cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* How this works:
|
||||
* - `socket` is the `WebSocket` instance, the connection to our broker.
|
||||
* - `proxy` is a `Transform`, it ensure data written to the `socket` is a `Buffer`.
|
||||
* This class buffers the data written to the `proxy` (so then to `socket`) until the `socket` is ready.
|
||||
* The stream returned from this class, will be passed to the `MqttClient`.
|
||||
*/
|
||||
export class BufferedDuplex extends Duplex {
|
||||
public socket: WebSocket
|
||||
|
||||
private proxy: Transform
|
||||
|
||||
private isSocketOpen: boolean
|
||||
|
||||
private writeQueue: Array<{
|
||||
chunk: any
|
||||
encoding: string
|
||||
cb: (err?: Error) => void
|
||||
}>
|
||||
|
||||
constructor(opts: IClientOptions, proxy: Transform, socket: WebSocket) {
|
||||
super({
|
||||
objectMode: true,
|
||||
})
|
||||
this.proxy = proxy
|
||||
this.socket = socket
|
||||
this.writeQueue = []
|
||||
|
||||
if (!opts.objectMode) {
|
||||
this._writev = writev.bind(this)
|
||||
}
|
||||
|
||||
this.isSocketOpen = false
|
||||
|
||||
this.proxy.on('data', (chunk) => {
|
||||
this.push(chunk)
|
||||
})
|
||||
}
|
||||
|
||||
_read(size?: number): void {
|
||||
this.proxy.read(size)
|
||||
}
|
||||
|
||||
_write(chunk: any, encoding: string, cb: (err?: Error) => void) {
|
||||
if (!this.isSocketOpen) {
|
||||
// Buffer the data in a queue
|
||||
this.writeQueue.push({ chunk, encoding, cb })
|
||||
} else {
|
||||
this.writeToProxy(chunk, encoding, cb)
|
||||
}
|
||||
}
|
||||
|
||||
_final(callback: (error?: Error) => void): void {
|
||||
this.writeQueue = []
|
||||
this.proxy.end(callback)
|
||||
}
|
||||
|
||||
/** Method to call when socket is ready to stop buffering writes */
|
||||
socketReady() {
|
||||
this.emit('connect')
|
||||
this.isSocketOpen = true
|
||||
this.processWriteQueue()
|
||||
}
|
||||
|
||||
private writeToProxy(
|
||||
chunk: any,
|
||||
encoding: string,
|
||||
cb: (err?: Error) => void,
|
||||
) {
|
||||
if (this.proxy.write(chunk, encoding) === false) {
|
||||
this.proxy.once('drain', cb)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
|
||||
private processWriteQueue() {
|
||||
while (this.writeQueue.length > 0) {
|
||||
const { chunk, encoding, cb } = this.writeQueue.shift()!
|
||||
this.writeToProxy(chunk, encoding, cb)
|
||||
}
|
||||
}
|
||||
}
|
45
VApp/node_modules/mqtt/src/lib/PingTimer.ts
generated
vendored
Normal file
45
VApp/node_modules/mqtt/src/lib/PingTimer.ts
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
import { clearTimeout as clearT, setTimeout as setT } from 'worker-timers'
|
||||
import isBrowser, { isWebWorker } from './is-browser'
|
||||
|
||||
export default class PingTimer {
|
||||
private keepalive: number
|
||||
|
||||
private timer: any
|
||||
|
||||
private checkPing: () => void
|
||||
|
||||
// dont directly assign globals to class props otherwise this throws in web workers: Uncaught TypeError: Illegal invocation
|
||||
// See: https://stackoverflow.com/questions/9677985/uncaught-typeerror-illegal-invocation-in-chrome
|
||||
private _setTimeout: typeof setT =
|
||||
isBrowser && !isWebWorker
|
||||
? setT
|
||||
: (func, time) => setTimeout(func, time)
|
||||
|
||||
private _clearTimeout: typeof clearT =
|
||||
isBrowser && !isWebWorker ? clearT : (timer) => clearTimeout(timer)
|
||||
|
||||
constructor(keepalive: number, checkPing: () => void) {
|
||||
this.keepalive = keepalive * 1000
|
||||
this.checkPing = checkPing
|
||||
this.reschedule()
|
||||
}
|
||||
|
||||
clear() {
|
||||
if (this.timer) {
|
||||
this._clearTimeout(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
}
|
||||
|
||||
reschedule() {
|
||||
this.clear()
|
||||
this.timer = this._setTimeout(() => {
|
||||
this.checkPing()
|
||||
// prevent possible race condition where the timer is destroyed on _cleauUp
|
||||
// and recreated here
|
||||
if (this.timer) {
|
||||
this.reschedule()
|
||||
}
|
||||
}, this.keepalive)
|
||||
}
|
||||
}
|
71
VApp/node_modules/mqtt/src/lib/TypedEmitter.ts
generated
vendored
Normal file
71
VApp/node_modules/mqtt/src/lib/TypedEmitter.ts
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
import EventEmitter from 'events'
|
||||
import { applyMixin } from './shared'
|
||||
|
||||
export type EventHandler =
|
||||
// Add more overloads as necessary
|
||||
| ((arg1: any, arg2: any, arg3: any, arg4: any) => void)
|
||||
| ((arg1: any, arg2: any, arg3: any) => void)
|
||||
| ((arg1: any, arg2: any) => void)
|
||||
| ((arg1: any) => void)
|
||||
| ((...args: any[]) => void)
|
||||
|
||||
export interface TypedEventEmitter<
|
||||
TEvents extends Record<keyof TEvents, EventHandler>,
|
||||
> {
|
||||
on<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
once<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
prependListener<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
prependOnceListener<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
|
||||
removeListener<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
off<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
callback: TEvents[TEvent],
|
||||
): this
|
||||
|
||||
removeAllListeners(event?: keyof TEvents): this
|
||||
|
||||
emit<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
...args: Parameters<TEvents[TEvent]>
|
||||
): boolean
|
||||
|
||||
setMaxListeners(n: number): this
|
||||
getMaxListeners(): number
|
||||
|
||||
listeners<TEvent extends keyof TEvents>(
|
||||
eventName: TEvent,
|
||||
): TEvents[TEvent][]
|
||||
rawListeners<TEvent extends keyof TEvents>(
|
||||
eventName: TEvent,
|
||||
): TEvents[TEvent][]
|
||||
listenerCount<TEvent extends keyof TEvents>(
|
||||
event: TEvent,
|
||||
listener?: TEvents[TEvent],
|
||||
): number
|
||||
|
||||
eventNames(): Array<keyof TEvents>
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
||||
export class TypedEventEmitter<
|
||||
TEvents extends Record<keyof TEvents, EventHandler>,
|
||||
> {}
|
||||
|
||||
// Make TypedEventEmitter inherit from EventEmitter without actually extending
|
||||
applyMixin(TypedEventEmitter, EventEmitter)
|
2322
VApp/node_modules/mqtt/src/lib/client.ts
generated
vendored
Normal file
2322
VApp/node_modules/mqtt/src/lib/client.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
127
VApp/node_modules/mqtt/src/lib/connect/ali.ts
generated
vendored
Normal file
127
VApp/node_modules/mqtt/src/lib/connect/ali.ts
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
import { Buffer } from 'buffer'
|
||||
import { Transform } from 'readable-stream'
|
||||
import { StreamBuilder } from '../shared'
|
||||
import MqttClient, { IClientOptions } from '../client'
|
||||
import { BufferedDuplex } from '../BufferedDuplex'
|
||||
|
||||
let my: any
|
||||
let proxy: Transform
|
||||
let stream: BufferedDuplex
|
||||
let isInitialized = false
|
||||
|
||||
function buildProxy() {
|
||||
const _proxy = new Transform()
|
||||
_proxy._write = (chunk, encoding, next) => {
|
||||
my.sendSocketMessage({
|
||||
data: chunk.buffer,
|
||||
success() {
|
||||
next()
|
||||
},
|
||||
fail() {
|
||||
next(new Error())
|
||||
},
|
||||
})
|
||||
}
|
||||
_proxy._flush = (done) => {
|
||||
my.closeSocket({
|
||||
success() {
|
||||
done()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return _proxy
|
||||
}
|
||||
|
||||
function setDefaultOpts(opts: IClientOptions) {
|
||||
if (!opts.hostname) {
|
||||
opts.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.path) {
|
||||
opts.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
opts.wsOptions = {}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUrl(opts: IClientOptions, client: MqttClient) {
|
||||
const protocol = opts.protocol === 'alis' ? 'wss' : 'ws'
|
||||
let url = `${protocol}://${opts.hostname}${opts.path}`
|
||||
if (opts.port && opts.port !== 80 && opts.port !== 443) {
|
||||
url = `${protocol}://${opts.hostname}:${opts.port}${opts.path}`
|
||||
}
|
||||
if (typeof opts.transformWsUrl === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function bindEventHandler() {
|
||||
if (isInitialized) return
|
||||
|
||||
isInitialized = true
|
||||
|
||||
my.onSocketOpen(() => {
|
||||
stream.socketReady()
|
||||
})
|
||||
|
||||
my.onSocketMessage((res) => {
|
||||
if (typeof res.data === 'string') {
|
||||
const buffer = Buffer.from(res.data, 'base64')
|
||||
proxy.push(buffer)
|
||||
} else {
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener('load', () => {
|
||||
let data = reader.result
|
||||
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data, 'utf8')
|
||||
proxy.push(data)
|
||||
})
|
||||
reader.readAsArrayBuffer(res.data)
|
||||
}
|
||||
})
|
||||
|
||||
my.onSocketClose(() => {
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
})
|
||||
|
||||
my.onSocketError((err) => {
|
||||
stream.destroy(err)
|
||||
})
|
||||
}
|
||||
|
||||
const buildStream: StreamBuilder = (client, opts) => {
|
||||
opts.hostname = opts.hostname || opts.host
|
||||
|
||||
if (!opts.hostname) {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
|
||||
const websocketSubProtocol =
|
||||
opts.protocolId === 'MQIsdp' && opts.protocolVersion === 3
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
setDefaultOpts(opts)
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
my = opts.my
|
||||
// https://miniprogram.alipay.com/docs/miniprogram/mpdev/api_network_connectsocket
|
||||
my.connectSocket({
|
||||
url,
|
||||
protocols: websocketSubProtocol,
|
||||
})
|
||||
|
||||
proxy = buildProxy()
|
||||
stream = new BufferedDuplex(opts, proxy, my)
|
||||
|
||||
bindEventHandler()
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
export default buildStream
|
241
VApp/node_modules/mqtt/src/lib/connect/index.ts
generated
vendored
Normal file
241
VApp/node_modules/mqtt/src/lib/connect/index.ts
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import _debug from 'debug'
|
||||
import url from 'url'
|
||||
import MqttClient, {
|
||||
IClientOptions,
|
||||
MqttClientEventCallbacks,
|
||||
MqttProtocol,
|
||||
} from '../client'
|
||||
import IS_BROWSER from '../is-browser'
|
||||
import { StreamBuilder } from '../shared'
|
||||
|
||||
const debug = _debug('mqttjs')
|
||||
|
||||
const protocols: Record<string, StreamBuilder> = {}
|
||||
|
||||
if (!IS_BROWSER) {
|
||||
protocols.mqtt = require('./tcp').default
|
||||
protocols.tcp = require('./tcp').default
|
||||
protocols.ssl = require('./tls').default
|
||||
protocols.tls = protocols.ssl
|
||||
protocols.mqtts = require('./tls').default
|
||||
} else {
|
||||
protocols.wx = require('./wx').default
|
||||
protocols.wxs = require('./wx').default
|
||||
|
||||
protocols.ali = require('./ali').default
|
||||
protocols.alis = require('./ali').default
|
||||
}
|
||||
|
||||
protocols.ws = require('./ws').default
|
||||
protocols.wss = require('./ws').default
|
||||
|
||||
/**
|
||||
* Parse the auth attribute and merge username and password in the options object.
|
||||
*
|
||||
* @param {Object} [opts] option object
|
||||
*/
|
||||
function parseAuthOptions(opts: IClientOptions) {
|
||||
let matches: RegExpMatchArray | null
|
||||
if (opts.auth) {
|
||||
matches = opts.auth.match(/^(.+):(.+)$/)
|
||||
if (matches) {
|
||||
opts.username = matches[1]
|
||||
opts.password = matches[2]
|
||||
} else {
|
||||
opts.username = opts.auth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* connect - connect to an MQTT broker.
|
||||
*/
|
||||
function connect(brokerUrl: string): MqttClient
|
||||
function connect(opts: IClientOptions): MqttClient
|
||||
function connect(brokerUrl: string, opts?: IClientOptions): MqttClient
|
||||
function connect(
|
||||
brokerUrl: string | IClientOptions,
|
||||
opts?: IClientOptions,
|
||||
): MqttClient {
|
||||
debug('connecting to an MQTT broker...')
|
||||
if (typeof brokerUrl === 'object' && !opts) {
|
||||
opts = brokerUrl
|
||||
brokerUrl = ''
|
||||
}
|
||||
|
||||
opts = opts || {}
|
||||
|
||||
if (brokerUrl && typeof brokerUrl === 'string') {
|
||||
// eslint-disable-next-line
|
||||
const parsed = url.parse(brokerUrl, true)
|
||||
if (parsed.port != null) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
parsed.port = Number(parsed.port)
|
||||
}
|
||||
|
||||
opts = { ...parsed, ...opts } as IClientOptions
|
||||
|
||||
if (opts.protocol === null) {
|
||||
throw new Error('Missing protocol')
|
||||
}
|
||||
|
||||
opts.protocol = opts.protocol.replace(/:$/, '') as MqttProtocol
|
||||
}
|
||||
|
||||
// merge in the auth options if supplied
|
||||
parseAuthOptions(opts)
|
||||
|
||||
// support clientId passed in the query string of the url
|
||||
if (opts.query && typeof opts.query.clientId === 'string') {
|
||||
opts.clientId = opts.query.clientId
|
||||
}
|
||||
|
||||
if (opts.cert && opts.key) {
|
||||
if (opts.protocol) {
|
||||
if (['mqtts', 'wss', 'wxs', 'alis'].indexOf(opts.protocol) === -1) {
|
||||
switch (opts.protocol) {
|
||||
case 'mqtt':
|
||||
opts.protocol = 'mqtts'
|
||||
break
|
||||
case 'ws':
|
||||
opts.protocol = 'wss'
|
||||
break
|
||||
case 'wx':
|
||||
opts.protocol = 'wxs'
|
||||
break
|
||||
case 'ali':
|
||||
opts.protocol = 'alis'
|
||||
break
|
||||
default:
|
||||
throw new Error(
|
||||
`Unknown protocol for secure connection: "${opts.protocol}"!`,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A cert and key was provided, however no protocol was specified, so we will throw an error.
|
||||
throw new Error('Missing secure protocol key')
|
||||
}
|
||||
}
|
||||
|
||||
if (!protocols[opts.protocol]) {
|
||||
const isSecure = ['mqtts', 'wss'].indexOf(opts.protocol) !== -1
|
||||
opts.protocol = [
|
||||
'mqtt',
|
||||
'mqtts',
|
||||
'ws',
|
||||
'wss',
|
||||
'wx',
|
||||
'wxs',
|
||||
'ali',
|
||||
'alis',
|
||||
].filter((key, index) => {
|
||||
if (isSecure && index % 2 === 0) {
|
||||
// Skip insecure protocols when requesting a secure one.
|
||||
return false
|
||||
}
|
||||
return typeof protocols[key] === 'function'
|
||||
})[0] as MqttProtocol
|
||||
}
|
||||
|
||||
if (opts.clean === false && !opts.clientId) {
|
||||
throw new Error('Missing clientId for unclean clients')
|
||||
}
|
||||
|
||||
if (opts.protocol) {
|
||||
opts.defaultProtocol = opts.protocol
|
||||
}
|
||||
|
||||
function wrapper(client: MqttClient) {
|
||||
if (opts.servers) {
|
||||
if (
|
||||
!client._reconnectCount ||
|
||||
client._reconnectCount === opts.servers.length
|
||||
) {
|
||||
client._reconnectCount = 0
|
||||
}
|
||||
|
||||
opts.host = opts.servers[client._reconnectCount].host
|
||||
opts.port = opts.servers[client._reconnectCount].port
|
||||
opts.protocol = !opts.servers[client._reconnectCount].protocol
|
||||
? opts.defaultProtocol
|
||||
: opts.servers[client._reconnectCount].protocol
|
||||
opts.hostname = opts.host
|
||||
|
||||
client._reconnectCount++
|
||||
}
|
||||
|
||||
debug('calling streambuilder for', opts.protocol)
|
||||
return protocols[opts.protocol](client, opts)
|
||||
}
|
||||
const client = new MqttClient(wrapper, opts)
|
||||
client.on('error', () => {
|
||||
/* Automatically set up client error handling */
|
||||
})
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
function connectAsync(brokerUrl: string): Promise<MqttClient>
|
||||
function connectAsync(opts: IClientOptions): Promise<MqttClient>
|
||||
function connectAsync(
|
||||
brokerUrl: string,
|
||||
opts?: IClientOptions,
|
||||
): Promise<MqttClient>
|
||||
function connectAsync(
|
||||
brokerUrl: string | IClientOptions,
|
||||
opts?: IClientOptions,
|
||||
allowRetries = true,
|
||||
): Promise<MqttClient> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = connect(brokerUrl as string, opts)
|
||||
|
||||
const promiseResolutionListeners: Partial<MqttClientEventCallbacks> = {
|
||||
connect: (connack) => {
|
||||
removePromiseResolutionListeners()
|
||||
resolve(client) // Resolve on connect
|
||||
},
|
||||
end: () => {
|
||||
removePromiseResolutionListeners()
|
||||
resolve(client) // Resolve on end
|
||||
},
|
||||
error: (err) => {
|
||||
removePromiseResolutionListeners()
|
||||
client.end()
|
||||
reject(err) // Reject on error
|
||||
},
|
||||
}
|
||||
|
||||
// If retries are not allowed, reject on close
|
||||
if (allowRetries === false) {
|
||||
promiseResolutionListeners.close = () => {
|
||||
promiseResolutionListeners.error(
|
||||
new Error("Couldn't connect to server"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove listeners added to client by this promise
|
||||
function removePromiseResolutionListeners() {
|
||||
Object.keys(promiseResolutionListeners).forEach((eventName) => {
|
||||
client.off(
|
||||
eventName as keyof MqttClientEventCallbacks,
|
||||
promiseResolutionListeners[eventName],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// Add listeners to client
|
||||
Object.keys(promiseResolutionListeners).forEach((eventName) => {
|
||||
client.on(
|
||||
eventName as keyof MqttClientEventCallbacks,
|
||||
promiseResolutionListeners[eventName],
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default connect
|
||||
export { connectAsync }
|
23
VApp/node_modules/mqtt/src/lib/connect/tcp.ts
generated
vendored
Normal file
23
VApp/node_modules/mqtt/src/lib/connect/tcp.ts
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import { StreamBuilder } from '../shared'
|
||||
|
||||
import net from 'net'
|
||||
import _debug from 'debug'
|
||||
import { Duplex } from 'readable-stream'
|
||||
|
||||
const debug = _debug('mqttjs:tcp')
|
||||
/*
|
||||
variables port and host can be removed since
|
||||
you have all required information in opts object
|
||||
*/
|
||||
const buildStream: StreamBuilder = (client, opts) => {
|
||||
opts.port = opts.port || 1883
|
||||
opts.hostname = opts.hostname || opts.host || 'localhost'
|
||||
|
||||
const { port } = opts
|
||||
const host = opts.hostname
|
||||
|
||||
debug('port %d and host %s', port, host)
|
||||
return net.createConnection(port, host)
|
||||
}
|
||||
|
||||
export default buildStream
|
54
VApp/node_modules/mqtt/src/lib/connect/tls.ts
generated
vendored
Normal file
54
VApp/node_modules/mqtt/src/lib/connect/tls.ts
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
import tls from 'tls'
|
||||
import net from 'net'
|
||||
import _debug from 'debug'
|
||||
import { StreamBuilder } from '../shared'
|
||||
|
||||
const debug = _debug('mqttjs:tls')
|
||||
|
||||
const buildStream: StreamBuilder = (client, opts) => {
|
||||
opts.port = opts.port || 8883
|
||||
opts.host = opts.hostname || opts.host || 'localhost'
|
||||
|
||||
if (net.isIP(opts.host) === 0) {
|
||||
opts.servername = opts.host
|
||||
}
|
||||
|
||||
opts.rejectUnauthorized = opts.rejectUnauthorized !== false
|
||||
|
||||
delete opts.path
|
||||
|
||||
debug(
|
||||
'port %d host %s rejectUnauthorized %b',
|
||||
opts.port,
|
||||
opts.host,
|
||||
opts.rejectUnauthorized,
|
||||
)
|
||||
|
||||
const connection = tls.connect(opts)
|
||||
connection.on('secureConnect', () => {
|
||||
if (opts.rejectUnauthorized && !connection.authorized) {
|
||||
connection.emit('error', new Error('TLS not authorized'))
|
||||
} else {
|
||||
connection.removeListener('error', handleTLSerrors)
|
||||
}
|
||||
})
|
||||
|
||||
function handleTLSerrors(err: Error) {
|
||||
// How can I get verify this error is a tls error?
|
||||
if (opts.rejectUnauthorized) {
|
||||
client.emit('error', err)
|
||||
}
|
||||
|
||||
// close this connection to match the behaviour of net
|
||||
// otherwise all we get is an error from the connection
|
||||
// and close event doesn't fire. This is a work around
|
||||
// to enable the reconnect code to work the same as with
|
||||
// net.createConnection
|
||||
connection.end()
|
||||
}
|
||||
|
||||
connection.on('error', handleTLSerrors)
|
||||
return connection
|
||||
}
|
||||
|
||||
export default buildStream
|
297
VApp/node_modules/mqtt/src/lib/connect/ws.ts
generated
vendored
Normal file
297
VApp/node_modules/mqtt/src/lib/connect/ws.ts
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
import { StreamBuilder } from '../shared'
|
||||
import { Buffer } from 'buffer'
|
||||
import Ws, { ClientOptions } from 'ws'
|
||||
import _debug from 'debug'
|
||||
import { DuplexOptions, Transform } from 'readable-stream'
|
||||
import IS_BROWSER from '../is-browser'
|
||||
import MqttClient, { IClientOptions } from '../client'
|
||||
import { BufferedDuplex, writev } from '../BufferedDuplex'
|
||||
|
||||
const debug = _debug('mqttjs:ws')
|
||||
|
||||
const WSS_OPTIONS = [
|
||||
'rejectUnauthorized',
|
||||
'ca',
|
||||
'cert',
|
||||
'key',
|
||||
'pfx',
|
||||
'passphrase',
|
||||
]
|
||||
|
||||
function buildUrl(opts: IClientOptions, client: MqttClient) {
|
||||
let url = `${opts.protocol}://${opts.hostname}:${opts.port}${opts.path}`
|
||||
if (typeof opts.transformWsUrl === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function setDefaultOpts(opts: IClientOptions) {
|
||||
const options = opts
|
||||
if (!opts.hostname) {
|
||||
options.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.port) {
|
||||
if (opts.protocol === 'wss') {
|
||||
options.port = 443
|
||||
} else {
|
||||
options.port = 80
|
||||
}
|
||||
}
|
||||
if (!opts.path) {
|
||||
options.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
options.wsOptions = {}
|
||||
}
|
||||
if (!IS_BROWSER && opts.protocol === 'wss') {
|
||||
// Add cert/key/ca etc options
|
||||
WSS_OPTIONS.forEach((prop) => {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(opts, prop) &&
|
||||
!Object.prototype.hasOwnProperty.call(opts.wsOptions, prop)
|
||||
) {
|
||||
options.wsOptions[prop] = opts[prop]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function setDefaultBrowserOpts(opts: IClientOptions) {
|
||||
const options = setDefaultOpts(opts)
|
||||
|
||||
if (!options.hostname) {
|
||||
options.hostname = options.host
|
||||
}
|
||||
|
||||
if (!options.hostname) {
|
||||
// Throwing an error in a Web Worker if no `hostname` is given, because we
|
||||
// can not determine the `hostname` automatically. If connecting to
|
||||
// localhost, please supply the `hostname` as an argument.
|
||||
if (typeof document === 'undefined') {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
const parsed = new URL(document.URL)
|
||||
options.hostname = parsed.hostname
|
||||
|
||||
if (!options.port) {
|
||||
options.port = Number(parsed.port)
|
||||
}
|
||||
}
|
||||
|
||||
// objectMode should be defined for logic
|
||||
if (options.objectMode === undefined) {
|
||||
options.objectMode = !(
|
||||
options.binary === true || options.binary === undefined
|
||||
)
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function createWebSocket(
|
||||
client: MqttClient,
|
||||
url: string,
|
||||
opts: IClientOptions,
|
||||
) {
|
||||
debug('createWebSocket')
|
||||
debug(`protocol: ${opts.protocolId} ${opts.protocolVersion}`)
|
||||
const websocketSubProtocol =
|
||||
opts.protocolId === 'MQIsdp' && opts.protocolVersion === 3
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
debug(
|
||||
`creating new Websocket for url: ${url} and protocol: ${websocketSubProtocol}`,
|
||||
)
|
||||
let socket: Ws
|
||||
if (opts.createWebsocket) {
|
||||
socket = opts.createWebsocket(url, [websocketSubProtocol], opts)
|
||||
} else {
|
||||
socket = new Ws(
|
||||
url,
|
||||
[websocketSubProtocol],
|
||||
opts.wsOptions as ClientOptions,
|
||||
)
|
||||
}
|
||||
return socket
|
||||
}
|
||||
|
||||
function createBrowserWebSocket(client: MqttClient, opts: IClientOptions) {
|
||||
const websocketSubProtocol =
|
||||
opts.protocolId === 'MQIsdp' && opts.protocolVersion === 3
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
let socket: WebSocket
|
||||
if (opts.createWebsocket) {
|
||||
socket = opts.createWebsocket(url, [websocketSubProtocol], opts)
|
||||
} else {
|
||||
socket = new WebSocket(url, [websocketSubProtocol])
|
||||
}
|
||||
socket.binaryType = 'arraybuffer'
|
||||
return socket
|
||||
}
|
||||
|
||||
const streamBuilder: StreamBuilder = (client, opts) => {
|
||||
debug('streamBuilder')
|
||||
const options = setDefaultOpts(opts)
|
||||
const url = buildUrl(options, client)
|
||||
const socket = createWebSocket(client, url, options)
|
||||
const webSocketStream = Ws.createWebSocketStream(
|
||||
socket,
|
||||
options.wsOptions as DuplexOptions,
|
||||
)
|
||||
|
||||
webSocketStream['url'] = url
|
||||
socket.on('close', () => {
|
||||
webSocketStream.destroy()
|
||||
})
|
||||
return webSocketStream
|
||||
}
|
||||
|
||||
const browserStreamBuilder: StreamBuilder = (client, opts) => {
|
||||
debug('browserStreamBuilder')
|
||||
let stream: BufferedDuplex | (Transform & { socket?: WebSocket })
|
||||
const options = setDefaultBrowserOpts(opts)
|
||||
// sets the maximum socket buffer size before throttling
|
||||
const bufferSize = options.browserBufferSize || 1024 * 512
|
||||
|
||||
const bufferTimeout = opts.browserBufferTimeout || 1000
|
||||
|
||||
const coerceToBuffer = !opts.objectMode
|
||||
|
||||
// the websocket connection
|
||||
const socket = createBrowserWebSocket(client, opts)
|
||||
|
||||
// the proxy is a transform stream that forwards data to the socket
|
||||
// it ensures data written to socket is a Buffer
|
||||
const proxy = buildProxy(opts, socketWriteBrowser, socketEndBrowser)
|
||||
|
||||
if (!opts.objectMode) {
|
||||
proxy._writev = writev.bind(proxy)
|
||||
}
|
||||
proxy.on('close', () => {
|
||||
socket.close()
|
||||
})
|
||||
|
||||
const eventListenerSupport = typeof socket.addEventListener !== 'undefined'
|
||||
|
||||
// was already open when passed in
|
||||
if (socket.readyState === socket.OPEN) {
|
||||
stream = proxy
|
||||
stream.socket = socket
|
||||
} else {
|
||||
// socket is not open. Use this to buffer writes until it is opened
|
||||
stream = new BufferedDuplex(opts, proxy, socket)
|
||||
|
||||
if (eventListenerSupport) {
|
||||
socket.addEventListener('open', onOpen)
|
||||
} else {
|
||||
socket.onopen = onOpen
|
||||
}
|
||||
}
|
||||
|
||||
if (eventListenerSupport) {
|
||||
socket.addEventListener('close', onClose)
|
||||
socket.addEventListener('error', onError)
|
||||
socket.addEventListener('message', onMessage)
|
||||
} else {
|
||||
socket.onclose = onClose
|
||||
socket.onerror = onError
|
||||
socket.onmessage = onMessage
|
||||
}
|
||||
|
||||
// methods for browserStreamBuilder
|
||||
|
||||
function buildProxy(
|
||||
pOptions: IClientOptions,
|
||||
socketWrite: typeof socketWriteBrowser,
|
||||
socketEnd: typeof socketEndBrowser,
|
||||
) {
|
||||
const _proxy = new Transform({
|
||||
objectMode: pOptions.objectMode,
|
||||
})
|
||||
|
||||
_proxy._write = socketWrite
|
||||
_proxy._flush = socketEnd
|
||||
|
||||
return _proxy
|
||||
}
|
||||
|
||||
function onOpen() {
|
||||
debug('WebSocket onOpen')
|
||||
if (stream instanceof BufferedDuplex) {
|
||||
stream.socketReady()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event
|
||||
*/
|
||||
function onClose(event: CloseEvent) {
|
||||
debug('WebSocket onClose', event)
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
}
|
||||
|
||||
/**
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event
|
||||
*/
|
||||
function onError(err: Event) {
|
||||
debug('WebSocket onError', err)
|
||||
const error = new Error('WebSocket error')
|
||||
error['event'] = err
|
||||
stream.destroy(error)
|
||||
}
|
||||
|
||||
/**
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event
|
||||
*/
|
||||
function onMessage(event: MessageEvent) {
|
||||
let { data } = event
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data as string, 'utf8')
|
||||
proxy.push(data)
|
||||
}
|
||||
|
||||
function socketWriteBrowser(
|
||||
chunk: any,
|
||||
enc: string,
|
||||
next: (err?: Error) => void,
|
||||
) {
|
||||
if (socket.bufferedAmount > bufferSize) {
|
||||
// throttle data until buffered amount is reduced.
|
||||
setTimeout(socketWriteBrowser, bufferTimeout, chunk, enc, next)
|
||||
return
|
||||
}
|
||||
|
||||
if (coerceToBuffer && typeof chunk === 'string') {
|
||||
chunk = Buffer.from(chunk, 'utf8')
|
||||
}
|
||||
|
||||
try {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send (note this doesn't have a cb as second arg)
|
||||
socket.send(chunk)
|
||||
} catch (err) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
function socketEndBrowser(done: (error?: Error, data?: any) => void) {
|
||||
socket.close()
|
||||
done()
|
||||
}
|
||||
|
||||
// end methods for browserStreamBuilder
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
export default IS_BROWSER ? browserStreamBuilder : streamBuilder
|
142
VApp/node_modules/mqtt/src/lib/connect/wx.ts
generated
vendored
Normal file
142
VApp/node_modules/mqtt/src/lib/connect/wx.ts
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
import { StreamBuilder } from '../shared'
|
||||
|
||||
import { Buffer } from 'buffer'
|
||||
import { Transform } from 'readable-stream'
|
||||
import MqttClient, { IClientOptions } from '../client'
|
||||
import { BufferedDuplex } from '../BufferedDuplex'
|
||||
|
||||
/* global wx */
|
||||
let socketTask: any
|
||||
let proxy: Transform
|
||||
let stream: BufferedDuplex
|
||||
|
||||
declare global {
|
||||
const wx: any
|
||||
}
|
||||
|
||||
function buildProxy() {
|
||||
const _proxy = new Transform()
|
||||
_proxy._write = (chunk, encoding, next) => {
|
||||
socketTask.send({
|
||||
data: chunk.buffer,
|
||||
success() {
|
||||
next()
|
||||
},
|
||||
fail(errMsg) {
|
||||
next(new Error(errMsg))
|
||||
},
|
||||
})
|
||||
}
|
||||
_proxy._flush = (done) => {
|
||||
socketTask.close({
|
||||
success() {
|
||||
done()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return _proxy
|
||||
}
|
||||
|
||||
function setDefaultOpts(opts) {
|
||||
if (!opts.hostname) {
|
||||
opts.hostname = 'localhost'
|
||||
}
|
||||
if (!opts.path) {
|
||||
opts.path = '/'
|
||||
}
|
||||
|
||||
if (!opts.wsOptions) {
|
||||
opts.wsOptions = {}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUrl(opts: IClientOptions, client: MqttClient) {
|
||||
const protocol = opts.protocol === 'wxs' ? 'wss' : 'ws'
|
||||
let url = `${protocol}://${opts.hostname}${opts.path}`
|
||||
if (opts.port && opts.port !== 80 && opts.port !== 443) {
|
||||
url = `${protocol}://${opts.hostname}:${opts.port}${opts.path}`
|
||||
}
|
||||
if (typeof opts.transformWsUrl === 'function') {
|
||||
url = opts.transformWsUrl(url, opts, client)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
function bindEventHandler() {
|
||||
socketTask.onOpen(() => {
|
||||
stream.socketReady()
|
||||
})
|
||||
|
||||
socketTask.onMessage((res) => {
|
||||
let { data } = res
|
||||
|
||||
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
||||
else data = Buffer.from(data, 'utf8')
|
||||
proxy.push(data)
|
||||
})
|
||||
|
||||
socketTask.onClose(() => {
|
||||
stream.emit('close')
|
||||
stream.end()
|
||||
stream.destroy()
|
||||
})
|
||||
|
||||
socketTask.onError((error) => {
|
||||
const err = new Error(error.errMsg)
|
||||
stream.destroy(err)
|
||||
})
|
||||
}
|
||||
|
||||
const buildStream: StreamBuilder = (client, opts) => {
|
||||
opts.hostname = opts.hostname || opts.host
|
||||
|
||||
if (!opts.hostname) {
|
||||
throw new Error('Could not determine host. Specify host manually.')
|
||||
}
|
||||
|
||||
const websocketSubProtocol =
|
||||
opts.protocolId === 'MQIsdp' && opts.protocolVersion === 3
|
||||
? 'mqttv3.1'
|
||||
: 'mqtt'
|
||||
|
||||
setDefaultOpts(opts)
|
||||
|
||||
const url = buildUrl(opts, client)
|
||||
// https://github.com/wechat-miniprogram/api-typings/blob/master/types/wx/lib.wx.api.d.ts#L20984
|
||||
socketTask = wx.connectSocket({
|
||||
url,
|
||||
protocols: [websocketSubProtocol],
|
||||
})
|
||||
|
||||
proxy = buildProxy()
|
||||
stream = new BufferedDuplex(opts, proxy, socketTask)
|
||||
stream._destroy = (err, cb) => {
|
||||
socketTask.close({
|
||||
success() {
|
||||
if (cb) cb(err)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const destroyRef = stream.destroy
|
||||
stream.destroy = (err, cb) => {
|
||||
stream.destroy = destroyRef
|
||||
|
||||
setTimeout(() => {
|
||||
socketTask.close({
|
||||
fail() {
|
||||
stream._destroy(err, cb)
|
||||
},
|
||||
})
|
||||
}, 0)
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
bindEventHandler()
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
export default buildStream
|
99
VApp/node_modules/mqtt/src/lib/default-message-id-provider.ts
generated
vendored
Normal file
99
VApp/node_modules/mqtt/src/lib/default-message-id-provider.ts
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
export interface IMessageIdProvider {
|
||||
/**
|
||||
* Allocate the first vacant messageId. The messageId become occupied status.
|
||||
* @return {Number} - The first vacant messageId. If all messageIds are occupied, return null.
|
||||
*/
|
||||
allocate(): number | null
|
||||
|
||||
/**
|
||||
* Get the last allocated messageId.
|
||||
* @return {Number} - messageId.
|
||||
*/
|
||||
getLastAllocated(): number | null
|
||||
|
||||
/**
|
||||
* Register the messageId. The messageId become occupied status.
|
||||
* If the messageId has already been occupied, then return false.
|
||||
* @param {number} num - The messageId to request use.
|
||||
* @return {boolean} - If `num` was not occupied, then return true, otherwise return false.
|
||||
*/
|
||||
register(num: number): boolean
|
||||
|
||||
/**
|
||||
* Deallocate the messageId. The messageId become vacant status.
|
||||
* @param {Number} num - The messageId to deallocate. The messageId must be occupied status.
|
||||
* In other words, the messageId must be allocated by allocate() or
|
||||
* occupied by register().
|
||||
*/
|
||||
deallocate(num: number): void
|
||||
|
||||
/**
|
||||
* Clear all occupied messageIds.
|
||||
* The all messageIds are set to vacant status.
|
||||
*/
|
||||
clear(): void
|
||||
}
|
||||
|
||||
/**
|
||||
* DefaultMessageAllocator constructor
|
||||
* @constructor
|
||||
*/
|
||||
export default class DefaultMessageIdProvider implements IMessageIdProvider {
|
||||
private nextId: number
|
||||
|
||||
constructor() {
|
||||
/**
|
||||
* MessageIDs starting with 1
|
||||
* ensure that nextId is min. 1, see https://github.com/mqttjs/MQTT.js/issues/810
|
||||
*/
|
||||
this.nextId = Math.max(1, Math.floor(Math.random() * 65535))
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate
|
||||
*
|
||||
* Get the next messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
allocate() {
|
||||
// id becomes current state of this.nextId and increments afterwards
|
||||
const id = this.nextId++
|
||||
// Ensure 16 bit unsigned int (max 65535, nextId got one higher)
|
||||
if (this.nextId === 65536) {
|
||||
this.nextId = 1
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastAllocated
|
||||
* Get the last allocated messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
getLastAllocated() {
|
||||
return this.nextId === 1 ? 65535 : this.nextId - 1
|
||||
}
|
||||
|
||||
/**
|
||||
* register
|
||||
* Register messageId. If success return true, otherwise return false.
|
||||
* @param { unsigned int } - messageId to register,
|
||||
* @return boolean
|
||||
*/
|
||||
register(messageId: number) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* deallocate
|
||||
* Deallocate messageId.
|
||||
* @param { unsigned int } - messageId to deallocate,
|
||||
*/
|
||||
deallocate(messageId: number) {}
|
||||
|
||||
/**
|
||||
* clear
|
||||
* Deallocate all messageIds.
|
||||
*/
|
||||
clear() {}
|
||||
}
|
151
VApp/node_modules/mqtt/src/lib/handlers/ack.ts
generated
vendored
Normal file
151
VApp/node_modules/mqtt/src/lib/handlers/ack.ts
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
// Other Socket Errors: EADDRINUSE, ECONNRESET, ENOTFOUND, ETIMEDOUT.
|
||||
|
||||
import { PacketHandler } from '../shared'
|
||||
|
||||
export const ReasonCodes = {
|
||||
0: '',
|
||||
1: 'Unacceptable protocol version',
|
||||
2: 'Identifier rejected',
|
||||
3: 'Server unavailable',
|
||||
4: 'Bad username or password',
|
||||
5: 'Not authorized',
|
||||
16: 'No matching subscribers',
|
||||
17: 'No subscription existed',
|
||||
128: 'Unspecified error',
|
||||
129: 'Malformed Packet',
|
||||
130: 'Protocol Error',
|
||||
131: 'Implementation specific error',
|
||||
132: 'Unsupported Protocol Version',
|
||||
133: 'Client Identifier not valid',
|
||||
134: 'Bad User Name or Password',
|
||||
135: 'Not authorized',
|
||||
136: 'Server unavailable',
|
||||
137: 'Server busy',
|
||||
138: 'Banned',
|
||||
139: 'Server shutting down',
|
||||
140: 'Bad authentication method',
|
||||
141: 'Keep Alive timeout',
|
||||
142: 'Session taken over',
|
||||
143: 'Topic Filter invalid',
|
||||
144: 'Topic Name invalid',
|
||||
145: 'Packet identifier in use',
|
||||
146: 'Packet Identifier not found',
|
||||
147: 'Receive Maximum exceeded',
|
||||
148: 'Topic Alias invalid',
|
||||
149: 'Packet too large',
|
||||
150: 'Message rate too high',
|
||||
151: 'Quota exceeded',
|
||||
152: 'Administrative action',
|
||||
153: 'Payload format invalid',
|
||||
154: 'Retain not supported',
|
||||
155: 'QoS not supported',
|
||||
156: 'Use another server',
|
||||
157: 'Server moved',
|
||||
158: 'Shared Subscriptions not supported',
|
||||
159: 'Connection rate exceeded',
|
||||
160: 'Maximum connect time',
|
||||
161: 'Subscription Identifiers not supported',
|
||||
162: 'Wildcard Subscriptions not supported',
|
||||
}
|
||||
|
||||
const handleAck: PacketHandler = (client, packet) => {
|
||||
/* eslint no-fallthrough: "off" */
|
||||
const { messageId } = packet
|
||||
const type = packet.cmd
|
||||
let response = null
|
||||
const cb = client.outgoing[messageId] ? client.outgoing[messageId].cb : null
|
||||
let err
|
||||
|
||||
// Checking `!cb` happens to work, but it's not technically "correct".
|
||||
//
|
||||
// Why? client code assumes client "no callback" is the same as client "we're not
|
||||
// waiting for responses" (puback, pubrec, pubcomp, suback, or unsuback).
|
||||
//
|
||||
// It would be better to check `if (!client.outgoing[messageId])` here, but
|
||||
// there's no reason to change it and risk (another) regression.
|
||||
//
|
||||
// The only reason client code works is becaues code in MqttClient.publish,
|
||||
// MqttClinet.subscribe, and MqttClient.unsubscribe ensures client we will
|
||||
// have a callback even if the user doesn't pass one in.)
|
||||
if (!cb) {
|
||||
client.log('_handleAck :: Server sent an ack in error. Ignoring.')
|
||||
// Server sent an ack in error, ignore it.
|
||||
return
|
||||
}
|
||||
|
||||
// Process
|
||||
client.log('_handleAck :: packet type', type)
|
||||
switch (type) {
|
||||
case 'pubcomp':
|
||||
// same thing as puback for QoS 2
|
||||
case 'puback': {
|
||||
const pubackRC = packet.reasonCode
|
||||
// Callback - we're done
|
||||
if (pubackRC && pubackRC > 0 && pubackRC !== 16) {
|
||||
err = new Error(`Publish error: ${ReasonCodes[pubackRC]}`)
|
||||
err.code = pubackRC
|
||||
client['_removeOutgoingAndStoreMessage'](messageId, () => {
|
||||
cb(err, packet)
|
||||
})
|
||||
} else {
|
||||
client['_removeOutgoingAndStoreMessage'](messageId, cb)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
case 'pubrec': {
|
||||
response = {
|
||||
cmd: 'pubrel',
|
||||
qos: 2,
|
||||
messageId,
|
||||
}
|
||||
const pubrecRC = packet.reasonCode
|
||||
|
||||
if (pubrecRC && pubrecRC > 0 && pubrecRC !== 16) {
|
||||
err = new Error(`Publish error: ${ReasonCodes[pubrecRC]}`)
|
||||
err.code = pubrecRC
|
||||
client['_removeOutgoingAndStoreMessage'](messageId, () => {
|
||||
cb(err, packet)
|
||||
})
|
||||
} else {
|
||||
client['_sendPacket'](response)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'suback': {
|
||||
delete client.outgoing[messageId]
|
||||
client.messageIdProvider.deallocate(messageId)
|
||||
const granted = packet.granted as number[]
|
||||
for (let grantedI = 0; grantedI < granted.length; grantedI++) {
|
||||
if ((granted[grantedI] & 0x80) !== 0) {
|
||||
// suback with Failure status
|
||||
const topics = client.messageIdToTopic[messageId]
|
||||
if (topics) {
|
||||
topics.forEach((topic) => {
|
||||
delete client['_resubscribeTopics'][topic]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
delete client.messageIdToTopic[messageId]
|
||||
client['_invokeStoreProcessingQueue']()
|
||||
cb(null, packet)
|
||||
break
|
||||
}
|
||||
case 'unsuback': {
|
||||
delete client.outgoing[messageId]
|
||||
client.messageIdProvider.deallocate(messageId)
|
||||
client['_invokeStoreProcessingQueue']()
|
||||
cb(null)
|
||||
break
|
||||
}
|
||||
default:
|
||||
client.emit('error', new Error('unrecognized packet type'))
|
||||
}
|
||||
|
||||
if (client.disconnecting && Object.keys(client.outgoing).length === 0) {
|
||||
client.emit('outgoingEmpty')
|
||||
}
|
||||
}
|
||||
|
||||
export default handleAck
|
44
VApp/node_modules/mqtt/src/lib/handlers/auth.ts
generated
vendored
Normal file
44
VApp/node_modules/mqtt/src/lib/handlers/auth.ts
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
import { IAuthPacket } from 'mqtt-packet'
|
||||
import { ErrorWithReasonCode, PacketHandler } from '../shared'
|
||||
import { ReasonCodes } from './ack'
|
||||
|
||||
const handleAuth: PacketHandler = (
|
||||
client,
|
||||
packet: IAuthPacket & { returnCode: number },
|
||||
) => {
|
||||
const { options } = client
|
||||
const version = options.protocolVersion
|
||||
const rc = version === 5 ? packet.reasonCode : packet.returnCode
|
||||
|
||||
if (version !== 5) {
|
||||
const err = new ErrorWithReasonCode(
|
||||
`Protocol error: Auth packets are only supported in MQTT 5. Your version:${version}`,
|
||||
rc,
|
||||
)
|
||||
client.emit('error', err)
|
||||
return
|
||||
}
|
||||
|
||||
client.handleAuth(
|
||||
packet,
|
||||
(err: ErrorWithReasonCode, packet2: IAuthPacket) => {
|
||||
if (err) {
|
||||
client.emit('error', err)
|
||||
return
|
||||
}
|
||||
|
||||
if (rc === 24) {
|
||||
client.reconnecting = false
|
||||
client['_sendPacket'](packet2)
|
||||
} else {
|
||||
const error = new ErrorWithReasonCode(
|
||||
`Connection refused: ${ReasonCodes[rc]}`,
|
||||
rc,
|
||||
)
|
||||
client.emit('error', error)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export default handleAuth
|
55
VApp/node_modules/mqtt/src/lib/handlers/connack.ts
generated
vendored
Normal file
55
VApp/node_modules/mqtt/src/lib/handlers/connack.ts
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
import { ReasonCodes } from './ack'
|
||||
import TopicAliasSend from '../topic-alias-send'
|
||||
import { ErrorWithReasonCode, PacketHandler } from '../shared'
|
||||
import { IConnackPacket } from 'mqtt-packet'
|
||||
|
||||
const handleConnack: PacketHandler = (client, packet: IConnackPacket) => {
|
||||
client.log('_handleConnack')
|
||||
const { options } = client
|
||||
const version = options.protocolVersion
|
||||
const rc = version === 5 ? packet.reasonCode : packet.returnCode
|
||||
|
||||
clearTimeout(client['connackTimer'])
|
||||
delete client['topicAliasSend']
|
||||
|
||||
if (packet.properties) {
|
||||
if (packet.properties.topicAliasMaximum) {
|
||||
if (packet.properties.topicAliasMaximum > 0xffff) {
|
||||
client.emit(
|
||||
'error',
|
||||
new Error('topicAliasMaximum from broker is out of range'),
|
||||
)
|
||||
return
|
||||
}
|
||||
if (packet.properties.topicAliasMaximum > 0) {
|
||||
client['topicAliasSend'] = new TopicAliasSend(
|
||||
packet.properties.topicAliasMaximum,
|
||||
)
|
||||
}
|
||||
}
|
||||
if (packet.properties.serverKeepAlive && options.keepalive) {
|
||||
options.keepalive = packet.properties.serverKeepAlive
|
||||
client['_shiftPingInterval']()
|
||||
}
|
||||
if (packet.properties.maximumPacketSize) {
|
||||
if (!options.properties) {
|
||||
options.properties = {}
|
||||
}
|
||||
options.properties.maximumPacketSize =
|
||||
packet.properties.maximumPacketSize
|
||||
}
|
||||
}
|
||||
|
||||
if (rc === 0) {
|
||||
client.reconnecting = false
|
||||
client['_onConnect'](packet)
|
||||
} else if (rc > 0) {
|
||||
const err = new ErrorWithReasonCode(
|
||||
`Connection refused: ${ReasonCodes[rc]}`,
|
||||
rc,
|
||||
)
|
||||
client.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
export default handleConnack
|
67
VApp/node_modules/mqtt/src/lib/handlers/index.ts
generated
vendored
Normal file
67
VApp/node_modules/mqtt/src/lib/handlers/index.ts
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
import handlePublish from './publish'
|
||||
import handleAuth from './auth'
|
||||
import handleConnack from './connack'
|
||||
import handleAck from './ack'
|
||||
import handlePubrel from './pubrel'
|
||||
import { PacketHandler } from '../shared'
|
||||
|
||||
const handle: PacketHandler = (client, packet, done) => {
|
||||
const { options } = client
|
||||
|
||||
if (
|
||||
options.protocolVersion === 5 &&
|
||||
options.properties &&
|
||||
options.properties.maximumPacketSize &&
|
||||
options.properties.maximumPacketSize < packet.length
|
||||
) {
|
||||
client.emit('error', new Error(`exceeding packets size ${packet.cmd}`))
|
||||
client.end({
|
||||
reasonCode: 149,
|
||||
properties: { reasonString: 'Maximum packet size was exceeded' },
|
||||
})
|
||||
return client
|
||||
}
|
||||
client.log('_handlePacket :: emitting packetreceive')
|
||||
client.emit('packetreceive', packet)
|
||||
|
||||
switch (packet.cmd) {
|
||||
case 'publish':
|
||||
handlePublish(client, packet, done)
|
||||
break
|
||||
case 'puback':
|
||||
case 'pubrec':
|
||||
case 'pubcomp':
|
||||
case 'suback':
|
||||
case 'unsuback':
|
||||
handleAck(client, packet)
|
||||
done()
|
||||
break
|
||||
case 'pubrel':
|
||||
handlePubrel(client, packet, done)
|
||||
break
|
||||
case 'connack':
|
||||
handleConnack(client, packet)
|
||||
done()
|
||||
break
|
||||
case 'auth':
|
||||
handleAuth(client, packet)
|
||||
done()
|
||||
break
|
||||
case 'pingresp':
|
||||
// this will be checked in _checkPing client method every keepalive interval
|
||||
client.pingResp = true
|
||||
done()
|
||||
break
|
||||
case 'disconnect':
|
||||
client.emit('disconnect', packet)
|
||||
done()
|
||||
break
|
||||
default:
|
||||
// TODO: unknown packet received. Should we emit an error?
|
||||
client.log('_handlePacket :: unknown command')
|
||||
done()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default handle
|
183
VApp/node_modules/mqtt/src/lib/handlers/publish.ts
generated
vendored
Normal file
183
VApp/node_modules/mqtt/src/lib/handlers/publish.ts
generated
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
import { IPublishPacket } from 'mqtt-packet'
|
||||
import { PacketHandler } from '../shared'
|
||||
|
||||
const validReasonCodes = [0, 16, 128, 131, 135, 144, 145, 151, 153]
|
||||
|
||||
/*
|
||||
those late 2 case should be rewrite to comply with coding style:
|
||||
|
||||
case 1:
|
||||
case 0:
|
||||
// do not wait sending a puback
|
||||
// no callback passed
|
||||
if (1 === qos) {
|
||||
this._sendPacket({
|
||||
cmd: 'puback',
|
||||
messageId: messageId
|
||||
});
|
||||
}
|
||||
// emit the message event for both qos 1 and 0
|
||||
this.emit('message', topic, message, packet);
|
||||
this.handleMessage(packet, done);
|
||||
break;
|
||||
default:
|
||||
// do nothing but every switch mus have a default
|
||||
// log or throw an error about unknown qos
|
||||
break;
|
||||
|
||||
for now i just suppressed the warnings
|
||||
*/
|
||||
const handlePublish: PacketHandler = (client, packet: IPublishPacket, done) => {
|
||||
client.log('handlePublish: packet %o', packet)
|
||||
done = typeof done !== 'undefined' ? done : client.noop
|
||||
let topic = packet.topic.toString()
|
||||
const message = packet.payload
|
||||
const { qos } = packet
|
||||
const { messageId } = packet
|
||||
const { options } = client
|
||||
if (client.options.protocolVersion === 5) {
|
||||
let alias: number
|
||||
if (packet.properties) {
|
||||
alias = packet.properties.topicAlias
|
||||
}
|
||||
if (typeof alias !== 'undefined') {
|
||||
if (topic.length === 0) {
|
||||
if (alias > 0 && alias <= 0xffff) {
|
||||
const gotTopic =
|
||||
client['topicAliasRecv'].getTopicByAlias(alias)
|
||||
if (gotTopic) {
|
||||
topic = gotTopic
|
||||
client.log(
|
||||
'handlePublish :: topic complemented by alias. topic: %s - alias: %d',
|
||||
topic,
|
||||
alias,
|
||||
)
|
||||
} else {
|
||||
client.log(
|
||||
'handlePublish :: unregistered topic alias. alias: %d',
|
||||
alias,
|
||||
)
|
||||
client.emit(
|
||||
'error',
|
||||
new Error('Received unregistered Topic Alias'),
|
||||
)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
client.log(
|
||||
'handlePublish :: topic alias out of range. alias: %d',
|
||||
alias,
|
||||
)
|
||||
client.emit(
|
||||
'error',
|
||||
new Error('Received Topic Alias is out of range'),
|
||||
)
|
||||
return
|
||||
}
|
||||
} else if (client['topicAliasRecv'].put(topic, alias)) {
|
||||
client.log(
|
||||
'handlePublish :: registered topic: %s - alias: %d',
|
||||
topic,
|
||||
alias,
|
||||
)
|
||||
} else {
|
||||
client.log(
|
||||
'handlePublish :: topic alias out of range. alias: %d',
|
||||
alias,
|
||||
)
|
||||
client.emit(
|
||||
'error',
|
||||
new Error('Received Topic Alias is out of range'),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
client.log('handlePublish: qos %d', qos)
|
||||
switch (qos) {
|
||||
case 2: {
|
||||
options.customHandleAcks(
|
||||
topic,
|
||||
message as Buffer,
|
||||
packet,
|
||||
(error, code) => {
|
||||
if (typeof error === 'number') {
|
||||
code = error
|
||||
error = null
|
||||
}
|
||||
if (error) {
|
||||
return client.emit('error', error as Error)
|
||||
}
|
||||
if (validReasonCodes.indexOf(code) === -1) {
|
||||
return client.emit(
|
||||
'error',
|
||||
new Error('Wrong reason code for pubrec'),
|
||||
)
|
||||
}
|
||||
if (code) {
|
||||
client['_sendPacket'](
|
||||
{ cmd: 'pubrec', messageId, reasonCode: code },
|
||||
done,
|
||||
)
|
||||
} else {
|
||||
client.incomingStore.put(packet, () => {
|
||||
client['_sendPacket'](
|
||||
{ cmd: 'pubrec', messageId },
|
||||
done,
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
break
|
||||
}
|
||||
case 1: {
|
||||
// emit the message event
|
||||
options.customHandleAcks(
|
||||
topic,
|
||||
message as Buffer,
|
||||
packet,
|
||||
(error, code) => {
|
||||
if (typeof error === 'number') {
|
||||
code = error
|
||||
error = null
|
||||
}
|
||||
if (error) {
|
||||
return client.emit('error', error as Error)
|
||||
}
|
||||
if (validReasonCodes.indexOf(code) === -1) {
|
||||
return client.emit(
|
||||
'error',
|
||||
new Error('Wrong reason code for puback'),
|
||||
)
|
||||
}
|
||||
if (!code) {
|
||||
client.emit('message', topic, message as Buffer, packet)
|
||||
}
|
||||
client.handleMessage(packet, (err) => {
|
||||
if (err) {
|
||||
return done && done(err)
|
||||
}
|
||||
client['_sendPacket'](
|
||||
{ cmd: 'puback', messageId, reasonCode: code },
|
||||
done,
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
break
|
||||
}
|
||||
case 0:
|
||||
// emit the message event
|
||||
client.emit('message', topic, message as Buffer, packet)
|
||||
client.handleMessage(packet, done)
|
||||
break
|
||||
default:
|
||||
// do nothing
|
||||
client.log('handlePublish: unknown QoS. Doing nothing.')
|
||||
// log or throw an error about unknown qos
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default handlePublish
|
27
VApp/node_modules/mqtt/src/lib/handlers/pubrel.ts
generated
vendored
Normal file
27
VApp/node_modules/mqtt/src/lib/handlers/pubrel.ts
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
import { IPubcompPacket, IPublishPacket, IPubrelPacket } from 'mqtt-packet'
|
||||
import { PacketHandler } from '../shared'
|
||||
|
||||
const handlePubrel: PacketHandler = (client, packet: IPubrelPacket, done) => {
|
||||
client.log('handling pubrel packet')
|
||||
const callback = typeof done !== 'undefined' ? done : client.noop
|
||||
const { messageId } = packet
|
||||
|
||||
const comp: IPubcompPacket = { cmd: 'pubcomp', messageId }
|
||||
|
||||
client.incomingStore.get(packet, (err, pub: IPublishPacket) => {
|
||||
if (!err) {
|
||||
client.emit('message', pub.topic, pub.payload as Buffer, pub)
|
||||
client.handleMessage(pub, (err2) => {
|
||||
if (err2) {
|
||||
return callback(err2)
|
||||
}
|
||||
client.incomingStore.del(pub, client.noop)
|
||||
client['_sendPacket'](comp, callback)
|
||||
})
|
||||
} else {
|
||||
client['_sendPacket'](comp, callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default handlePubrel
|
20
VApp/node_modules/mqtt/src/lib/is-browser.ts
generated
vendored
Normal file
20
VApp/node_modules/mqtt/src/lib/is-browser.ts
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
const isStandardBrowserEnv = () =>
|
||||
typeof window !== 'undefined' && typeof window.document !== 'undefined'
|
||||
|
||||
const isWebWorkerEnv = () =>
|
||||
Boolean(
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
typeof self === 'object' &&
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
self?.constructor?.name?.includes('WorkerGlobalScope'),
|
||||
)
|
||||
|
||||
const isReactNativeEnv = () =>
|
||||
typeof navigator !== 'undefined' && navigator.product === 'ReactNative'
|
||||
|
||||
const isBrowser =
|
||||
isStandardBrowserEnv() || isWebWorkerEnv() || isReactNativeEnv()
|
||||
|
||||
export const isWebWorker = isWebWorkerEnv()
|
||||
|
||||
export default isBrowser
|
81
VApp/node_modules/mqtt/src/lib/shared.ts
generated
vendored
Normal file
81
VApp/node_modules/mqtt/src/lib/shared.ts
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
import type { Packet } from 'mqtt-packet'
|
||||
import type { Duplex } from 'stream'
|
||||
import type MqttClient from './client'
|
||||
import type { IClientOptions } from './client'
|
||||
|
||||
export type DoneCallback = (error?: Error) => void
|
||||
|
||||
export type GenericCallback<T> = (error?: Error, result?: T) => void
|
||||
|
||||
export type VoidCallback = () => void
|
||||
|
||||
export type IStream = Duplex & {
|
||||
/** only set on browsers, it's a [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) */
|
||||
socket?: any
|
||||
}
|
||||
|
||||
export type StreamBuilder = (
|
||||
client: MqttClient,
|
||||
opts?: IClientOptions,
|
||||
) => IStream
|
||||
|
||||
export type Callback = () => void
|
||||
|
||||
export type PacketHandler = (
|
||||
client: MqttClient,
|
||||
packet: Packet,
|
||||
done?: DoneCallback,
|
||||
) => void
|
||||
|
||||
export class ErrorWithReasonCode extends Error {
|
||||
public code: number
|
||||
|
||||
public constructor(message: string, code: number) {
|
||||
super(message)
|
||||
this.code = code
|
||||
|
||||
// We need to set the prototype explicitly
|
||||
Object.setPrototypeOf(this, ErrorWithReasonCode.prototype)
|
||||
Object.getPrototypeOf(this).name = 'ErrorWithReasonCode'
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type Constructor<T = {}> = new (...args: any[]) => T
|
||||
|
||||
export function applyMixin(
|
||||
target: Constructor,
|
||||
mixin: Constructor,
|
||||
includeConstructor = false,
|
||||
): void {
|
||||
// Figure out the inheritance chain of the mixin
|
||||
const inheritanceChain: Constructor[] = [mixin]
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const current = inheritanceChain[0]
|
||||
const base = Object.getPrototypeOf(current)
|
||||
if (base?.prototype) {
|
||||
inheritanceChain.unshift(base)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
for (const ctor of inheritanceChain) {
|
||||
for (const prop of Object.getOwnPropertyNames(ctor.prototype)) {
|
||||
// Do not override the constructor
|
||||
if (includeConstructor || prop !== 'constructor') {
|
||||
Object.defineProperty(
|
||||
target.prototype,
|
||||
prop,
|
||||
Object.getOwnPropertyDescriptor(ctor.prototype, prop) ??
|
||||
Object.create(null),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export const nextTick = process
|
||||
? process.nextTick
|
||||
: (callback: () => void) => {
|
||||
setTimeout(callback, 0)
|
||||
}
|
166
VApp/node_modules/mqtt/src/lib/store.ts
generated
vendored
Normal file
166
VApp/node_modules/mqtt/src/lib/store.ts
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import { Readable } from 'readable-stream'
|
||||
import { Packet } from 'mqtt-packet'
|
||||
import { DoneCallback } from './shared'
|
||||
|
||||
const streamsOpts = { objectMode: true }
|
||||
const defaultStoreOptions = {
|
||||
clean: true,
|
||||
}
|
||||
|
||||
export interface IStoreOptions {
|
||||
/**
|
||||
* true, clear _inflights at close
|
||||
*/
|
||||
clean?: boolean
|
||||
}
|
||||
|
||||
export type PacketCallback = (error?: Error, packet?: Packet) => void
|
||||
|
||||
export interface IStore {
|
||||
/**
|
||||
* Adds a packet to the store, a packet is
|
||||
* anything that has a messageId property.
|
||||
*
|
||||
*/
|
||||
put(packet: Packet, cb: DoneCallback): IStore
|
||||
|
||||
/**
|
||||
* Creates a stream with all the packets in the store
|
||||
*
|
||||
*/
|
||||
createStream(): Readable
|
||||
|
||||
/**
|
||||
* deletes a packet from the store.
|
||||
*/
|
||||
del(packet: Pick<Packet, 'messageId'>, cb: PacketCallback): IStore
|
||||
|
||||
/**
|
||||
* get a packet from the store.
|
||||
*/
|
||||
get(packet: Pick<Packet, 'messageId'>, cb: PacketCallback): IStore
|
||||
|
||||
/**
|
||||
* Close the store
|
||||
*/
|
||||
close(cb: DoneCallback): void
|
||||
}
|
||||
|
||||
/**
|
||||
* In-memory implementation of the message store
|
||||
* This can actually be saved into files.
|
||||
*
|
||||
* @param {Object} [options] - store options
|
||||
*/
|
||||
export default class Store implements IStore {
|
||||
private options: IStoreOptions
|
||||
|
||||
private _inflights: Map<number, Packet>
|
||||
|
||||
constructor(options?: IStoreOptions) {
|
||||
this.options = options || {}
|
||||
|
||||
// Defaults
|
||||
this.options = { ...defaultStoreOptions, ...options }
|
||||
|
||||
this._inflights = new Map()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a packet to the store, a packet is
|
||||
* anything that has a messageId property.
|
||||
*
|
||||
*/
|
||||
put(packet: Packet, cb: DoneCallback) {
|
||||
this._inflights.set(packet.messageId, packet)
|
||||
|
||||
if (cb) {
|
||||
cb()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream with all the packets in the store
|
||||
*
|
||||
*/
|
||||
createStream() {
|
||||
const stream = new Readable(streamsOpts)
|
||||
const values = []
|
||||
let destroyed = false
|
||||
let i = 0
|
||||
|
||||
this._inflights.forEach((value, key) => {
|
||||
values.push(value)
|
||||
})
|
||||
|
||||
stream._read = () => {
|
||||
if (!destroyed && i < values.length) {
|
||||
stream.push(values[i++])
|
||||
} else {
|
||||
stream.push(null)
|
||||
}
|
||||
}
|
||||
|
||||
stream.destroy = (err) => {
|
||||
if (destroyed) {
|
||||
return
|
||||
}
|
||||
|
||||
destroyed = true
|
||||
|
||||
setTimeout(() => {
|
||||
stream.emit('close')
|
||||
}, 0)
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a packet from the store.
|
||||
*/
|
||||
del(packet: Pick<Packet, 'messageId'>, cb: PacketCallback) {
|
||||
const toDelete = this._inflights.get(packet.messageId)
|
||||
if (toDelete) {
|
||||
this._inflights.delete(packet.messageId)
|
||||
cb(null, toDelete)
|
||||
} else if (cb) {
|
||||
cb(new Error('missing packet'))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* get a packet from the store.
|
||||
*/
|
||||
get(packet: Pick<Packet, 'messageId'>, cb: PacketCallback) {
|
||||
const storedPacket = this._inflights.get(packet.messageId)
|
||||
if (storedPacket) {
|
||||
cb(null, storedPacket)
|
||||
} else if (cb) {
|
||||
cb(new Error('missing packet'))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the store
|
||||
*/
|
||||
close(cb: DoneCallback) {
|
||||
if (this.options.clean) {
|
||||
this._inflights = null
|
||||
}
|
||||
if (cb) {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
}
|
48
VApp/node_modules/mqtt/src/lib/topic-alias-recv.ts
generated
vendored
Normal file
48
VApp/node_modules/mqtt/src/lib/topic-alias-recv.ts
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Topic Alias receiving manager
|
||||
* This holds alias to topic map
|
||||
* @param {Number} [max] - topic alias maximum entries
|
||||
*/
|
||||
export default class TopicAliasRecv {
|
||||
private aliasToTopic: Record<number, string>
|
||||
|
||||
public max: number
|
||||
|
||||
public length: number
|
||||
|
||||
constructor(max: number) {
|
||||
this.aliasToTopic = {}
|
||||
this.max = max
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update topic - alias entry.
|
||||
* @param {String} [topic] - topic
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {Boolean} - if success return true otherwise false
|
||||
*/
|
||||
put(topic: string, alias: number): boolean {
|
||||
if (alias === 0 || alias > this.max) {
|
||||
return false
|
||||
}
|
||||
this.aliasToTopic[alias] = topic
|
||||
this.length = Object.keys(this.aliasToTopic).length
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {String} [topic] - topic
|
||||
* @returns {Number} - if mapped topic exists return topic alias, otherwise return undefined
|
||||
*/
|
||||
getTopicByAlias(alias: number): string {
|
||||
return this.aliasToTopic[alias]
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all entries
|
||||
*/
|
||||
clear() {
|
||||
this.aliasToTopic = {}
|
||||
}
|
||||
}
|
96
VApp/node_modules/mqtt/src/lib/topic-alias-send.ts
generated
vendored
Normal file
96
VApp/node_modules/mqtt/src/lib/topic-alias-send.ts
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import { LRUCache } from 'lru-cache'
|
||||
import { NumberAllocator } from 'number-allocator'
|
||||
|
||||
/**
|
||||
* Topic Alias sending manager
|
||||
* This holds both topic to alias and alias to topic map
|
||||
* @param {Number} [max] - topic alias maximum entries
|
||||
*/
|
||||
export default class TopicAliasSend {
|
||||
private aliasToTopic: LRUCache<number, string>
|
||||
|
||||
private topicToAlias: Record<string, number>
|
||||
|
||||
private max: number
|
||||
|
||||
private numberAllocator: NumberAllocator
|
||||
|
||||
public length: number
|
||||
|
||||
constructor(max: number) {
|
||||
if (max > 0) {
|
||||
this.aliasToTopic = new LRUCache<number, string>({ max })
|
||||
this.topicToAlias = {}
|
||||
this.numberAllocator = new NumberAllocator(1, max)
|
||||
this.max = max
|
||||
this.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update topic - alias entry.
|
||||
* @param {String} [topic] - topic
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {Boolean} - if success return true otherwise false
|
||||
*/
|
||||
put(topic: string, alias: number): boolean {
|
||||
if (alias === 0 || alias > this.max) {
|
||||
return false
|
||||
}
|
||||
const entry = this.aliasToTopic.get(alias)
|
||||
if (entry) {
|
||||
delete this.topicToAlias[entry]
|
||||
}
|
||||
this.aliasToTopic.set(alias, topic)
|
||||
this.topicToAlias[topic] = alias
|
||||
this.numberAllocator.use(alias)
|
||||
this.length = this.aliasToTopic.size
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {Number} [alias] - topic alias
|
||||
* @returns {String} - if mapped topic exists return topic, otherwise return undefined
|
||||
*/
|
||||
getTopicByAlias(alias: number): string {
|
||||
return this.aliasToTopic.get(alias)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get topic by alias
|
||||
* @param {String} [topic] - topic
|
||||
* @returns {Number} - if mapped topic exists return topic alias, otherwise return undefined
|
||||
*/
|
||||
getAliasByTopic(topic: string): number | undefined {
|
||||
const alias = this.topicToAlias[topic]
|
||||
if (typeof alias !== 'undefined') {
|
||||
this.aliasToTopic.get(alias) // LRU update
|
||||
}
|
||||
return alias
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all entries
|
||||
*/
|
||||
clear() {
|
||||
this.aliasToTopic.clear()
|
||||
this.topicToAlias = {}
|
||||
this.numberAllocator.clear()
|
||||
this.length = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Least Recently Used (LRU) topic alias
|
||||
* @returns {Number} - if vacant alias exists then return it, otherwise then return LRU alias
|
||||
*/
|
||||
getLruAlias(): number {
|
||||
const alias = this.numberAllocator.firstVacant()
|
||||
if (alias) return alias
|
||||
// get last alias (key) from LRU cache
|
||||
return [...this.aliasToTopic.keys()][this.aliasToTopic.size - 1]
|
||||
}
|
||||
}
|
64
VApp/node_modules/mqtt/src/lib/unique-message-id-provider.ts
generated
vendored
Normal file
64
VApp/node_modules/mqtt/src/lib/unique-message-id-provider.ts
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
import { NumberAllocator } from 'number-allocator'
|
||||
import { IMessageIdProvider } from './default-message-id-provider'
|
||||
|
||||
/**
|
||||
* UniqueMessageAllocator constructor
|
||||
* @constructor
|
||||
*/
|
||||
export default class UniqueMessageIdProvider implements IMessageIdProvider {
|
||||
private numberAllocator: NumberAllocator
|
||||
|
||||
private lastId: number
|
||||
|
||||
constructor() {
|
||||
this.numberAllocator = new NumberAllocator(1, 65535)
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate
|
||||
*
|
||||
* Get the next messageId.
|
||||
* @return if messageId is fully allocated then return null,
|
||||
* otherwise return the smallest usable unsigned int messageId.
|
||||
*/
|
||||
allocate() {
|
||||
this.lastId = this.numberAllocator.alloc()
|
||||
return this.lastId
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastAllocated
|
||||
* Get the last allocated messageId.
|
||||
* @return unsigned int
|
||||
*/
|
||||
getLastAllocated() {
|
||||
return this.lastId
|
||||
}
|
||||
|
||||
/**
|
||||
* register
|
||||
* Register messageId. If success return true, otherwise return false.
|
||||
* @param { unsigned int } - messageId to register,
|
||||
* @return boolean
|
||||
*/
|
||||
register(messageId: number) {
|
||||
return this.numberAllocator.use(messageId) as boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* deallocate
|
||||
* Deallocate messageId.
|
||||
* @param { unsigned int } - messageId to deallocate,
|
||||
*/
|
||||
deallocate(messageId: number) {
|
||||
this.numberAllocator.free(messageId)
|
||||
}
|
||||
|
||||
/**
|
||||
* clear
|
||||
* Deallocate all messageIds.
|
||||
*/
|
||||
clear() {
|
||||
this.numberAllocator.clear()
|
||||
}
|
||||
}
|
46
VApp/node_modules/mqtt/src/lib/validations.ts
generated
vendored
Normal file
46
VApp/node_modules/mqtt/src/lib/validations.ts
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Validate a topic to see if it's valid or not.
|
||||
* A topic is valid if it follow below rules:
|
||||
* - Rule #1: If any part of the topic is not `+` or `#`, then it must not contain `+` and '#'
|
||||
* - Rule #2: Part `#` must be located at the end of the mailbox
|
||||
*
|
||||
* @param {String} topic - A topic
|
||||
* @returns {Boolean} If the topic is valid, returns true. Otherwise, returns false.
|
||||
*/
|
||||
export function validateTopic(topic: string): boolean {
|
||||
const parts = topic.split('/')
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (parts[i] === '+') {
|
||||
continue
|
||||
}
|
||||
|
||||
if (parts[i] === '#') {
|
||||
// for Rule #2
|
||||
return i === parts.length - 1
|
||||
}
|
||||
|
||||
if (parts[i].indexOf('+') !== -1 || parts[i].indexOf('#') !== -1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of topics to see if any of them is valid or not
|
||||
* @param {Array} topics - Array of topics
|
||||
* @returns {String} If the topics is valid, returns null. Otherwise, returns the invalid one
|
||||
*/
|
||||
export function validateTopics(topics: string[]): string {
|
||||
if (topics.length === 0) {
|
||||
return 'empty_topic_list'
|
||||
}
|
||||
for (let i = 0; i < topics.length; i++) {
|
||||
if (!validateTopic(topics[i])) {
|
||||
return topics[i]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
25
VApp/node_modules/mqtt/src/mqtt.ts
generated
vendored
Normal file
25
VApp/node_modules/mqtt/src/mqtt.ts
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2015 MQTT.js contributors.
|
||||
* Copyright (c) 2011-2014 Adam Rudd.
|
||||
*
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
import MqttClient from './lib/client'
|
||||
import DefaultMessageIdProvider from './lib/default-message-id-provider'
|
||||
import UniqueMessageIdProvider from './lib/unique-message-id-provider'
|
||||
import Store, { IStore } from './lib/store'
|
||||
import connect, { connectAsync } from './lib/connect'
|
||||
|
||||
export const Client = MqttClient
|
||||
export {
|
||||
connect,
|
||||
connectAsync,
|
||||
MqttClient,
|
||||
Store,
|
||||
DefaultMessageIdProvider,
|
||||
UniqueMessageIdProvider,
|
||||
IStore,
|
||||
}
|
||||
export * from './lib/client'
|
||||
export * from './lib/shared'
|
||||
export { ReasonCodes } from './lib/handlers/ack'
|
Reference in New Issue
Block a user