Tracking de l'application VApp (IHM du jeu)

This commit is contained in:
2025-05-11 18:04:12 +02:00
commit 89e9db9b62
17763 changed files with 3718499 additions and 0 deletions

39
VApp/node_modules/mqtt/src/bin/mqtt.ts generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

127
VApp/node_modules/mqtt/src/lib/connect/ali.ts generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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]
}
}

View 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
View 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
View 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'