├── .gitignore
├── img
├── banner.jpg
├── ap_config.png
├── logger_sn.png
├── config_hide.png
├── wifi_config.png
├── dummycloud_demo.png
├── firmware_version.png
└── dashboard_example_mock.png
├── dummycloud
├── Dockerfile
├── app.js
├── src
│ ├── util.js
│ ├── Logger.js
│ ├── DummyCloud.js
│ ├── Protocol.js
│ └── MqttClient.js
├── package.json
├── .automated.eslintrc.json
├── Readme.md
├── .eslintrc.json
├── LICENSE
└── package-lock.json
├── assets
└── deye_sun600.ksy
└── Readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /dummycloud/node_modules/
2 |
--------------------------------------------------------------------------------
/img/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/banner.jpg
--------------------------------------------------------------------------------
/img/ap_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/ap_config.png
--------------------------------------------------------------------------------
/img/logger_sn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/logger_sn.png
--------------------------------------------------------------------------------
/img/config_hide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/config_hide.png
--------------------------------------------------------------------------------
/img/wifi_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/wifi_config.png
--------------------------------------------------------------------------------
/img/dummycloud_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/dummycloud_demo.png
--------------------------------------------------------------------------------
/img/firmware_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/firmware_version.png
--------------------------------------------------------------------------------
/img/dashboard_example_mock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hypfer/deye-microinverter-cloud-free/HEAD/img/dashboard_example_mock.png
--------------------------------------------------------------------------------
/dummycloud/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-alpine
2 |
3 | WORKDIR /app
4 | ENV LOGLEVEL="info"
5 | ENV MQTT_BROKER_URL="mqtt://127.0.0.1"
6 |
7 | COPY package.json /app
8 | COPY package-lock.json /app
9 |
10 | RUN npm ci
11 | COPY . /app
12 |
13 | CMD ["npm", "start"]
--------------------------------------------------------------------------------
/dummycloud/app.js:
--------------------------------------------------------------------------------
1 | const DummyCloud = require("./src/DummyCloud");
2 | const Logger = require("./src/Logger");
3 | const MqttClient = require("./src/MqttClient");
4 |
5 | if (process.env.LOGLEVEL) {
6 | Logger.setLogLevel(process.env.LOGLEVEL);
7 | }
8 |
9 | const dummyCloud = new DummyCloud();
10 | const mqttClient = new MqttClient(dummyCloud);
11 |
12 | dummyCloud.initialize();
13 | mqttClient.initialize();
14 |
--------------------------------------------------------------------------------
/dummycloud/src/util.js:
--------------------------------------------------------------------------------
1 |
2 | function getKeyByValue(obj, value) {
3 | for (const key in obj) {
4 | // eslint-disable-next-line no-prototype-builtins
5 | if (obj.hasOwnProperty(key) && obj[key] === value) {
6 | return key;
7 | }
8 | }
9 | }
10 |
11 | function truncateToNullTerminator(str) {
12 | const nullTerminatorIndex = str.indexOf("\0");
13 | if (nullTerminatorIndex !== -1) {
14 | return str.slice(0, nullTerminatorIndex);
15 | } else {
16 | return str;
17 | }
18 | }
19 |
20 |
21 | module.exports = {
22 | getKeyByValue: getKeyByValue,
23 | truncateToNullTerminator: truncateToNullTerminator
24 | };
25 |
--------------------------------------------------------------------------------
/dummycloud/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deye-dummycloud",
3 | "version": "1.1.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "node app.js",
8 |
9 | "lint": "eslint -c .automated.eslintrc.json .",
10 | "lint_fix": "eslint -c .automated.eslintrc.json . --fix"
11 | },
12 | "author": "",
13 | "license": "Apache-2.0",
14 | "dependencies": {
15 | "mqtt": "^4.3.7"
16 | },
17 | "devDependencies": {
18 | "eslint": "8.16.0",
19 | "eslint-plugin-jsdoc": "48.9.3",
20 | "eslint-plugin-regexp": "1.7.0",
21 | "eslint-plugin-sort-keys-fix": "1.1.2",
22 | "eslint-plugin-sort-requires": "git+https://npm@github.com/Hypfer/eslint-plugin-sort-requires.git#2.1.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/dummycloud/.automated.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "brace-style": [
4 | "error",
5 | "1tbs"
6 | ],
7 | "no-trailing-spaces": [
8 | "error",
9 | {
10 | "ignoreComments": true
11 | }
12 | ],
13 | "keyword-spacing": "error",
14 | "eol-last": [
15 | "error",
16 | "always"
17 | ],
18 | "no-multi-spaces": [
19 | "error",
20 | {
21 | "ignoreEOLComments": true
22 | }
23 | ],
24 | "semi": [
25 | "error",
26 | "always"
27 | ],
28 | "quotes": [
29 | "error",
30 | "double"
31 | ],
32 | "indent": [
33 | "error",
34 | 4,
35 | {
36 | "SwitchCase": 1
37 | }
38 | ],
39 | "no-empty": "error"
40 | }
41 | }
--------------------------------------------------------------------------------
/dummycloud/Readme.md:
--------------------------------------------------------------------------------
1 | # Deye-dummycloud
2 |
3 | This is a small Node.js service that mocks the deye solarman cloud and publishes all the data to an MQTT broker.
4 | It also takes care of Home Assistant autodiscovery leading to things just working.
5 |
6 | 
7 |
8 | ## Usage
9 |
10 | The dummycloud is configured using environment variables to be container-friendly to use.
11 |
12 | - `LOGLEVEL` (defaults to `info`)
13 | - `MQTT_BROKER_URL` (no default. Should look like `mqtt://foo.bar`)
14 | - `MQTT_USERNAME` (no default, optional.)
15 | - `MQTT_PASSWORD` (no default, optional.)
16 | - `MQTT_CHECK_CERT` set to `false` for using `mqtts` with self signed certificate (defaults to `true`)
17 |
18 | ## Inverter Setup
19 |
20 | Using the `/config_hide.html` of the inverter webinterface, simply point `Server A Setting` and `Optional Server Setting` to the host this is running on.
21 | I'd still keep the firewall rules preventing the inverter from phoning home in place for good measure.
22 |
23 | ## Deployment
24 |
25 | The dummycloud can be started using `npm run start`. Next to this readme, there's also a dockerfile provided.
26 |
27 | A `docker-compose.yml` entry could for example look like this:
28 |
29 | ```yml
30 | deye-dummycloud:
31 | build:
32 | context: ./deye-microinverter-cloud-free/dummycloud/
33 | dockerfile: Dockerfile
34 | container_name: "deye-dummycloud"
35 | restart: always
36 | environment:
37 | - "LOGLEVEL=info"
38 | - "MQTT_BROKER_URL=mqtt://foobar.example"
39 | # User those variables if the MQTT broker requires username and password
40 | # - "MQTT_USERNAME=example-user"
41 | # - "MQTT_PASSWORD=example-password"
42 | ports:
43 | - "10000:10000"
44 | ```
45 |
--------------------------------------------------------------------------------
/dummycloud/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es6": true,
6 | "node": true,
7 | "mocha": true
8 | },
9 | "plugins": ["jsdoc", "sort-keys-fix", "sort-requires", "regexp"],
10 | "extends": ["eslint:recommended", "plugin:regexp/recommended"],
11 | "ignorePatterns": ["dist/*.js"],
12 | "globals": {
13 | "Atomics": "readonly",
14 | "SharedArrayBuffer": "readonly"
15 | },
16 | "parserOptions": {
17 | "ecmaVersion": 2020,
18 | "sourceType": "module"
19 | },
20 | "settings": {
21 | "jsdoc": {
22 | "mode": "closure",
23 | "tagNamePreference": {
24 | "returns": "returns",
25 | "augments": "extends"
26 | }
27 | }
28 | },
29 | "rules": {
30 | "no-labels": "error",
31 | "max-classes-per-file": "error",
32 | "eqeqeq": "error",
33 | "curly": "error",
34 | "default-case-last": "error",
35 | "block-scoped-var": "error",
36 | "no-new": "error",
37 | "no-multi-str": "error",
38 | "no-new-wrappers": "error",
39 | "no-sequences": "error",
40 | "no-self-compare": "error",
41 | "no-multi-assign": "error",
42 | "no-whitespace-before-property": "error",
43 | "no-magic-numbers": ["off", { "ignoreArrayIndexes": true }],
44 | "no-unused-vars": ["warn", { "args": "none" }],
45 | "jsdoc/check-alignment": "error",
46 | "jsdoc/check-param-names": "error",
47 | "jsdoc/check-tag-names": "error",
48 | "jsdoc/check-types": "error",
49 | "jsdoc/implements-on-classes": "error",
50 | "jsdoc/no-undefined-types": "error",
51 | "jsdoc/require-param": "error",
52 | "jsdoc/require-param-name": "error",
53 | "jsdoc/require-param-type": "error",
54 | "jsdoc/require-returns-check": "error",
55 | "jsdoc/require-returns-type": "error",
56 | "sort-requires/sort-requires": "warn",
57 | "operator-linebreak": ["error", "after"],
58 | "no-unneeded-ternary": ["error", { "defaultAssignment": false }],
59 | "arrow-body-style": ["error", "always"],
60 | "regexp/no-unused-capturing-group": "off",
61 |
62 |
63 |
64 | "no-empty": "off",
65 | "brace-style": "off",
66 | "no-trailing-spaces": "off",
67 | "keyword-spacing": "off",
68 | "eol-last": "off",
69 | "no-multi-spaces": "off",
70 | "semi": "off",
71 | "quotes": "off",
72 | "indent": "off",
73 | "no-extra-boolean-cast": "off"
74 |
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/dummycloud/src/Logger.js:
--------------------------------------------------------------------------------
1 | const util = require("util");
2 |
3 | class Logger {
4 | constructor() {
5 | this.logLevel = Logger.LogLevels["info"];
6 | }
7 |
8 | /**
9 | * @public
10 | * @return {string}
11 | */
12 | getLogLevel() {
13 | return Object.keys(Logger.LogLevels).find(key => {
14 | return Logger.LogLevels[key] === this.logLevel;
15 | });
16 | }
17 |
18 | /**
19 | * @public
20 | * @param {string} value
21 | */
22 | setLogLevel(value) {
23 | if (Logger.LogLevels[value] === undefined) {
24 | throw new Error(`Invalid log level '${value}', valid are '${Object.keys(Logger.LogLevels).join("','")}'`);
25 | } else {
26 | this.logLevel = Logger.LogLevels[value];
27 | }
28 | }
29 |
30 |
31 | /**
32 | * @private
33 | * @param {string} logLevel
34 | * @return {string}
35 | */
36 | buildLogLinePrefix(logLevel) {
37 | return `[${new Date().toISOString()}] [${logLevel}]`;
38 | }
39 |
40 | /**
41 | * @param {string} level
42 | * @param {...any} args
43 | * @private
44 | */
45 | log(level, ...args) {
46 | if (this.logLevel["level"] <= Logger.LogLevels[level]["level"]) {
47 | const logLinePrefix = this.buildLogLinePrefix(level.toUpperCase());
48 | const logLine = [logLinePrefix, ...args].map(arg => {
49 | if (typeof arg === "string") {
50 | return arg;
51 | }
52 |
53 | return util.inspect(
54 | arg,
55 | {
56 | depth: Infinity
57 | }
58 | );
59 | }).join(" ");
60 |
61 | Logger.LogLevels[level]["callback"](logLine);
62 | }
63 | }
64 |
65 | /**
66 | * @public
67 | * @see console.trace
68 | * @param {...any} args
69 | */
70 | trace(...args) {
71 | this.log("trace", ...args);
72 | }
73 |
74 | /**
75 | * @public
76 | * @see console.debug
77 | * @param {...any} args
78 | */
79 | debug(...args) {
80 | this.log("debug", ...args);
81 | }
82 |
83 | /**
84 | * @public
85 | * @see console.info
86 | * @param {...any} args
87 | */
88 | info(...args) {
89 | this.log("info", ...args);
90 | }
91 |
92 | /**
93 | * @public
94 | * @see console.warn
95 | * @param {...any} args
96 | */
97 | warn(...args) {
98 | this.log("warn", ...args);
99 | }
100 |
101 | /**
102 | * @public
103 | * @see console.error
104 | * @param {...any} args
105 | */
106 | error( ...args) {
107 | this.log("error", ...args);
108 | }
109 | }
110 |
111 | Logger.LogLevels = Object.freeze({
112 | // eslint-disable-next-line no-console
113 | "trace": {"level": -2, "callback": console.debug},
114 | // eslint-disable-next-line no-console
115 | "debug": {"level": -1, "callback": console.debug},
116 | // eslint-disable-next-line no-console
117 | "info": {"level": 0, "callback": console.info},
118 | // eslint-disable-next-line no-console
119 | "warn": {"level": 1, "callback": console.warn},
120 | // eslint-disable-next-line no-console
121 | "error": {"level": 2, "callback": console.error},
122 | });
123 |
124 | module.exports = new Logger();
125 |
--------------------------------------------------------------------------------
/dummycloud/src/DummyCloud.js:
--------------------------------------------------------------------------------
1 | const EventEmitter = require("events").EventEmitter;
2 | const Logger = require("./Logger");
3 | const net = require("net");
4 | const Protocol = require("./Protocol");
5 |
6 | class DummyCloud {
7 | constructor() {
8 | this.eventEmitter = new EventEmitter();
9 | this.server = new net.Server();
10 | }
11 |
12 | initialize() {
13 | this.server.listen(
14 | {
15 | port: DummyCloud.PORT,
16 | host: "0.0.0.0"
17 | },
18 | function() {
19 | Logger.info(`Starting deye-dummycloud on port ${DummyCloud.PORT}`);
20 | });
21 |
22 | this.server.on("connection", (socket) => {
23 | this.handleConnection(socket);
24 | });
25 | }
26 |
27 | /**
28 | * @private
29 | * @param {net.Socket} socket
30 | */
31 | handleConnection(socket) {
32 | const remoteAddress = socket.remoteAddress; // As this is a getter, it may become unavailable
33 | Logger.info(`New connection from ${remoteAddress}`);
34 |
35 | socket.on("data", (data) => {
36 | Logger.trace(new Date().toISOString(), `Data received from client ${remoteAddress}: ${data.toString()}`);
37 | Logger.trace(new Date().toISOString(), `Data ${remoteAddress}:`, data.toString("hex"));
38 |
39 | try {
40 | const packet = Protocol.parsePacket(data);
41 | let response;
42 |
43 | switch (packet.header.type) {
44 | case Protocol.MESSAGE_REQUEST_TYPES.HEARTBEAT: {
45 | response = Protocol.buildTimeResponse(packet);
46 | break;
47 | }
48 | case Protocol.MESSAGE_REQUEST_TYPES.WIFI: {
49 | /*
50 | There isn't much of interest in this packet
51 | It can contain the SSID or the Logger SN
52 | + Some counters increasing every second
53 |
54 | On connect, it also can contain the signal strength
55 | But that's about it
56 |
57 | The signal strength over time would've been interesting, but it only gets sent on connect
58 | With that, it's close to useless
59 | */
60 | response = Protocol.buildTimeResponse(packet);
61 | break;
62 | }
63 | case Protocol.MESSAGE_REQUEST_TYPES.HANDSHAKE: {
64 | const data = Protocol.parseLoggerPacketPayload(packet);
65 |
66 | Logger.debug(`Handshake packet data from ${remoteAddress}`, data);
67 | this.emitHandshake({
68 | header: packet.header,
69 | payload: data
70 | });
71 |
72 | response = Protocol.buildTimeResponse(packet);
73 | break;
74 | }
75 | case Protocol.MESSAGE_REQUEST_TYPES.DATA: {
76 | const data = Protocol.parseDataPacketPayload(packet);
77 |
78 | if (data) {
79 | Logger.debug(`DATA packet data from ${remoteAddress}`, data);
80 | this.emitData({
81 | header: packet.header,
82 | payload: data,
83 | meta: {
84 | remoteAddress: remoteAddress
85 | }
86 | });
87 | } else {
88 | Logger.debug("Discarded data packet");
89 | }
90 |
91 | response = Protocol.buildTimeResponse(packet);
92 | break;
93 | }
94 |
95 | default: {
96 | response = Protocol.buildTimeResponse(packet);
97 | }
98 | }
99 |
100 | if (response) {
101 | Logger.trace("Response", response.toString("hex"));
102 |
103 | socket.write(response);
104 | }
105 | } catch (e) {
106 | Logger.error(`Error while parsing packet from ${remoteAddress}`, e);
107 | }
108 | });
109 |
110 | socket.on("end", function() {
111 | Logger.info(`Ending connection with ${remoteAddress}`);
112 | });
113 |
114 | socket.on("close", function() {
115 | Logger.info(`Closing connection with ${remoteAddress}`);
116 | });
117 |
118 | socket.on("error", function(err) {
119 | Logger.error(`Error on dummycloud socket for ${remoteAddress}`, err);
120 | });
121 | }
122 |
123 | emitData(data) {
124 | this.eventEmitter.emit(DummyCloud.PACKET_EVENTS.Data, data);
125 | }
126 |
127 | onData(listener) {
128 | this.eventEmitter.on(DummyCloud.PACKET_EVENTS.Data, listener);
129 | }
130 |
131 | emitHandshake(data) {
132 | this.eventEmitter.emit(DummyCloud.PACKET_EVENTS.Handshake, data);
133 | }
134 |
135 | onHandshake(listener) {
136 | this.eventEmitter.on(DummyCloud.PACKET_EVENTS.Handshake, listener);
137 | }
138 | }
139 |
140 | DummyCloud.PACKET_EVENTS = {
141 | Data: "Data",
142 | Handshake: "Handshake"
143 | };
144 |
145 |
146 | DummyCloud.PORT = 10000;
147 |
148 | module.exports = DummyCloud;
149 |
--------------------------------------------------------------------------------
/assets/deye_sun600.ksy:
--------------------------------------------------------------------------------
1 | meta:
2 | id: deye_sun600
3 |
4 | seq:
5 | - id: header
6 | type: header
7 | - id: payload
8 | size: header.payload_length
9 | type:
10 | switch-on: header.msg_type
11 | cases:
12 | "msg_type::handshake": handshake_msg_payload
13 | "msg_type::data": data_msg_payload
14 | "msg_type::wifi": wifi_msg_payload
15 | "msg_type::command": command_msg_payload
16 | - id: footer
17 | type: footer
18 |
19 | types:
20 | header:
21 | seq:
22 | - id: magic
23 | contents: [0xa5]
24 | - id: payload_length
25 | type: u2le
26 | - id: unknown1
27 | type: u1
28 | - id: msg_type
29 | type: u1
30 | enum: msg_type
31 | - id: msg_id_response
32 | type: u1
33 | - id: msg_id_request
34 | type: u1
35 | - id: logger_sn
36 | type: u4le
37 | footer:
38 | seq:
39 | - id: checksum
40 | type: u1
41 | - id: magic
42 | contents: [0x15]
43 |
44 | command_msg_payload:
45 | seq:
46 | - size: 15
47 | - id: command
48 | type: str
49 | encoding: ASCII
50 | size-eos: true
51 |
52 | handshake_msg_payload:
53 | seq:
54 | - size: 13
55 | - size: 6
56 | - id: fw_ver
57 | type: str
58 | size: 40
59 | encoding: ASCII
60 | - size: 6
61 | - id: ip
62 | type: str
63 | size: 16
64 | encoding: ASCII
65 | - size: 8
66 | - id: version
67 | type: str
68 | size: 18
69 | encoding: ASCII
70 | - size: 65
71 | - id: ssid
72 | type: str
73 | size: 30
74 | encoding: ASCII
75 | - id: unknown
76 | size-eos: true
77 |
78 | data_msg_payload:
79 | seq:
80 | - id: payload_magic # Might be destination? 01 for logger, 02 for inverter, 129 for logger historic
81 | size: 1 # has to be carried over to the response
82 | - id: schema
83 | enum: data_msg_payload_schema
84 | type: u1
85 | - id: data
86 | size-eos: true
87 | type:
88 | switch-on: schema
89 | cases:
90 | "data_msg_payload_schema::microinverter": data_msg_payload_microinverter
91 | "data_msg_payload_schema::hybridinverter": data_msg_payload_hybridinverter
92 |
93 | data_msg_payload_hybridinverter:
94 | seq:
95 | - size: 1
96 | - id: unknown
97 | type: u4le
98 | - id: power_on_time
99 | type: u4le
100 | - id: unknown2
101 | type: u4le
102 | - size: 10
103 | - id: inverter_serial
104 | type: str
105 | size: 10
106 | encoding: ASCII
107 | - size: 6
108 | - id: some_string
109 | type: str
110 | size: 28
111 | encoding: ASCII
112 | - size: 26
113 | - id: energy_battery_charge_today
114 | type: s2be
115 | - id: energy_battery_discharge_today
116 | type: s2be
117 | - id: energy_battery_charge_total
118 | type: s4be
119 | - id: energy_battery_discharge_total
120 | type: s4be
121 | - id: energy_grid_import_today
122 | type: s2be
123 | - id: energy_grid_export_today
124 | type: s2be
125 | - id: energy_grid_import_total
126 | type: s4be
127 | - id: energy_grid_export_total
128 | type: s4be
129 | - id: energy_house_today
130 | type: s2be
131 | - id: energy_house_total
132 | type: s4be
133 |
134 | - size: 4
135 |
136 | - id: energy_pv_today
137 | type: s2be
138 | - id: energy_pv1_today # TODO
139 | type: s2be
140 | - id: energy_pv2_today # TODO
141 | type: s2be
142 | - id: energy_pv_total
143 | type: s4be
144 |
145 | - size: 34
146 |
147 | - id: battery_temp
148 | type: s2be
149 | - id: battery_voltage
150 | type: s2be
151 | - id: battery_soc_pct
152 | type: s2be
153 | - size: 2
154 | - id: battery_power
155 | type: s2be
156 | - id: battery_current
157 | type: s2be
158 | - id: battery_unknown
159 | type: s2be
160 |
161 | - id: grid_l1_n_voltage
162 | type: s2be
163 | - id: grid_l2_n_voltage
164 | type: s2be
165 | - id: grid_l3_n_voltage
166 | type: s2be
167 |
168 | - size: 8
169 |
170 | - id: grid_l1_power
171 | type: s2be
172 | - id: grid_l2_power
173 | type: s2be
174 | - id: grid_l3_power
175 | type: s2be
176 |
177 |
178 | data_msg_payload_microinverter:
179 | seq:
180 | - size: 5
181 | - id: unknown_counter_1
182 | type: u2be
183 | - size: 8
184 | - id: unknown_counter_2
185 | type: u2le
186 | - size: 2
187 | - id: inverter_id
188 | size: 10
189 | - id: unknown2
190 | type: u2le
191 | - id: kwh_today
192 | type: u4le
193 | - id: kwh_total
194 | type: u4le
195 | - size: 4
196 | - id: grid_v
197 | type: u2le
198 | - size: 4
199 | - id: grid_i
200 | type: u2le
201 | - size: 4
202 | - id: grid_freq_hz
203 | type: u2le
204 | - id: grid_active_power_w
205 | type: u4le
206 | - id: inverter_radiator_temp_celsius
207 | type: s2le
208 | - size: 20
209 | - id: pv_1_v
210 | type: u2le
211 | - id: pv_1_i
212 | type: u2le
213 | - id: pv_2_v
214 | type: u2le
215 | - id: pv_2_i
216 | type: u2le
217 | - id: pv_3_v
218 | type: u2le
219 | - id: pv_3_i
220 | type: u2le
221 | - id: pv_4_v
222 | type: u2le
223 | - id: pv_4_i
224 | type: u2le
225 | - id: protocol_ver
226 | type: str
227 | size: 8
228 | encoding: ASCII
229 | - id: dc_master_fw_version
230 | type: str
231 | size: 8
232 | encoding: ASCII
233 | - id: ac_fw_version
234 | type: str
235 | size: 8
236 | encoding: ASCII
237 | - size: 4
238 | - id: inverter_rated_power_w
239 | type: u2be
240 | - id: mppt_count
241 | type: u1
242 | - id: phase_count
243 | type: u1
244 | - size: 3
245 | - id: pv_1_kwh_today
246 | type: u2le
247 | - id: pv_2_kwh_today
248 | type: u2le
249 | - id: pv_3_kwh_today
250 | type: u2le
251 | - id: pv_4_kwh_today
252 | type: u2le
253 | - size: 1
254 | - id: pv_1_kwh_total
255 | type: u2be
256 | - size: 2
257 | - id: pv_2_kwh_total
258 | type: u2be
259 | - size: 2
260 | - id: pv_3_kwh_total
261 | type: u2be
262 | - size: 2
263 | - id: pv_4_kwh_total
264 | type: u2be
265 | - id: pv_ids
266 | size: 64
267 | - id: grid_freq_hz_overfreq_load_reduction_starting_point
268 | type: u2be
269 | - id: grid_overfreq_load_reduction_percent
270 | type: u2be
271 | - size: 8
272 | - id: grid_v_limit_upper
273 | type: u2be
274 | - id: grid_v_limit_lower
275 | type: u2be
276 | - id: grid_freq_hz_limit_upper
277 | type: u2be
278 | - id: grid_freq_hz_limit_lower
279 | type: u2be
280 | - id: startup_self_check_time
281 | type: u2be
282 | - id: current_time
283 | size: 6
284 |
285 |
286 | wifi_msg_payload:
287 | seq:
288 | - id: schema
289 | enum: wifi_msg_payload_schema
290 | type: u1
291 | - id: maybe_uptime
292 | type: u2le
293 | - id: some_count
294 | type: u2le
295 |
296 | - id: maybe_connection_time_seconds
297 | type: u2le
298 | - id: unknown2
299 | type: u2le
300 | - id: unknown3
301 | type: u2le
302 | - id: unknown5
303 | type: u2le
304 | - id: unknown7
305 | type: u1
306 | - id: unknonw8
307 | type: u1
308 | - id: data
309 | size-eos: true
310 | type:
311 | switch-on: schema
312 | cases:
313 | "wifi_msg_payload_schema::foo": wifi_msg_payload_baz #intentional
314 | "wifi_msg_payload_schema::bar": wifi_msg_payload_bar
315 | "wifi_msg_payload_schema::baz": wifi_msg_payload_baz
316 |
317 | wifi_msg_payload_bar:
318 | seq:
319 | - id: inverter_sn
320 | size: 10
321 | type: str
322 | encoding: ASCII
323 | - id: data
324 | size-eos: true
325 | wifi_msg_payload_baz:
326 | seq:
327 | - id: ssid
328 | type: str
329 | size: 30
330 | encoding: ASCII
331 | - id: signal_quality_pct
332 | type: u1
333 | - id: some_constant
334 | contents: [0x01]
335 |
336 |
337 | enums:
338 | msg_type:
339 | 0x11: "handshake_response"
340 | 0x12: "data_response"
341 | 0x17: "heartbeat_response"
342 | 0x41: "handshake"
343 | 0x42: "data"
344 | 0x43: "wifi"
345 | 0x45: "command"
346 | 0x47: "heartbeat"
347 |
348 | data_msg_payload_schema:
349 | 0x08: "microinverter"
350 | 0x11: "hybridinverter"
351 | 0x13: "relaymodule"
352 |
353 | wifi_msg_payload_schema:
354 | 0x01: "foo"
355 | 0x04: "bar"
356 | 0x81: "baz"
357 |
--------------------------------------------------------------------------------
/dummycloud/src/Protocol.js:
--------------------------------------------------------------------------------
1 | const Logger = require("./Logger");
2 | const {getKeyByValue, truncateToNullTerminator} = require("./util");
3 |
4 | const HEADER_LEN = 11;
5 | const FOOTER_LEN = 2;
6 |
7 | class Protocol {
8 | static parseHeader(buf) {
9 | const result = {
10 | magic: buf[0], //should be 0xa5
11 | payloadLength: buf.readUInt16LE(1),
12 | unknown1: buf[3],
13 | type: buf[4],
14 | msgIDResponse: buf[5],
15 | msgIDRequest: buf[6],
16 | loggerSerial: buf.readUint32LE(7)
17 | };
18 |
19 | if (result.magic !== 0xa5) {
20 | throw new Error("Invalid header magic: " + result.magic);
21 | }
22 |
23 | if (result.payloadLength + HEADER_LEN + FOOTER_LEN !== buf.length) {
24 | throw new Error("Payload length from header doesn't match packet length. Truncated?");
25 | }
26 |
27 | return result;
28 | }
29 |
30 | static parseFooter(buf) {
31 | const result = {
32 | checksum: buf[buf.length - 2],
33 | magic: buf[buf.length - 1] //should always be 0x15
34 | };
35 |
36 | if (result.magic !== 0x15) {
37 | throw new Error("Invalid footer magic: " + result.magic);
38 | }
39 |
40 | return result;
41 | }
42 |
43 | static checksum(msgBuf) {
44 | const slice = msgBuf.subarray(1, msgBuf.length - 2); //exclude magic bytes and checksum
45 | let sum = 0;
46 |
47 | for (let i = 0; i < slice.length; i++) {
48 | sum = (sum + slice[i]) & 255;
49 | }
50 |
51 | return sum & 255;
52 | }
53 |
54 |
55 | static parsePacket(buf) {
56 | const header = Protocol.parseHeader(buf);
57 |
58 | const typeStr = getKeyByValue(Protocol.MESSAGE_REQUEST_TYPES, header.type);
59 | if (typeStr) {
60 | Logger.debug(`Received packet of type "${typeStr}"`);
61 | } else {
62 | Logger.warn(`Received packet of unknown type "0x${header.type.toString(16)}"`);
63 | }
64 |
65 | return {
66 | header: header,
67 | payload: buf.subarray(HEADER_LEN, buf.length - FOOTER_LEN)
68 | };
69 | }
70 |
71 | static parseDataPacketPayload(packet) {
72 | switch (packet.payload[1]) {
73 | case Protocol.DATA_PACKET_SCHEMAS.MICROINVERTER:
74 | return Protocol.parseDataPacketMicroinverterPayload(packet);
75 | default:
76 | return null; //TODO: parse relay and string inverter packets
77 | }
78 |
79 |
80 | }
81 |
82 | static parseDataPacketMicroinverterPayload(packet) {
83 | if (!!(packet.payload[0] & 0b10000000)) {
84 | // Seems to be one of these weird historic data packets from the SUN-M series. Ignoring for now
85 | // TODO: understand what they mean and how they should be handled
86 | return null;
87 | }
88 |
89 | //TODO: there's a lot more in this packet
90 |
91 | return {
92 | pv: {
93 | "1": {
94 | v: packet.payload.readUInt16LE(85) / 10,
95 | i: packet.payload.readUInt16LE(87) / 10,
96 |
97 | w: parseFloat(((packet.payload.readUInt16LE(85) / 10) * (packet.payload.readUInt16LE(87) / 10)).toFixed(2)),
98 |
99 | kWh_today: packet.payload.readUInt16LE(136) / 10,
100 | kWh_total: packet.payload.readUInt16BE(145) / 10,
101 | },
102 | "2": {
103 | v: packet.payload.readUInt16LE(89) / 10,
104 | i: packet.payload.readUInt16LE(91) / 10,
105 |
106 | w: parseFloat(((packet.payload.readUInt16LE(89) / 10) * (packet.payload.readUInt16LE(91) / 10)).toFixed(2)),
107 |
108 | kWh_today: packet.payload.readUInt16LE(138) / 10,
109 | kWh_total: packet.payload.readUInt16BE(149) / 10,
110 | },
111 | "3": {
112 | v: packet.payload.readUInt16LE(93) / 10,
113 | i: packet.payload.readUInt16LE(95) / 10,
114 |
115 | w: parseFloat(((packet.payload.readUInt16LE(93) / 10) * (packet.payload.readUInt16LE(95) / 10)).toFixed(2)),
116 |
117 | kWh_today: packet.payload.readUInt16LE(140) / 10,
118 | kWh_total: packet.payload.readUInt16BE(153) / 10,
119 | },
120 | "4": {
121 | v: packet.payload.readUInt16LE(97) / 10,
122 | i: packet.payload.readUInt16LE(99) / 10,
123 |
124 | w: parseFloat(((packet.payload.readUInt16LE(97) / 10) * (packet.payload.readUInt16LE(99) / 10)).toFixed(2)),
125 |
126 | kWh_today: packet.payload.readUInt16LE(142) / 10,
127 | kWh_total: packet.payload.readUInt16BE(157) / 10,
128 | },
129 | },
130 | grid: {
131 | active_power_w: packet.payload.readUInt32LE(59),
132 |
133 | kWh_today: packet.payload.readUInt32LE(33) / 100,
134 | kWh_total: packet.payload.readUInt32LE(37) / 10,
135 |
136 | v: packet.payload.readUInt16LE(45) / 10,
137 | i: packet.payload.readUInt16LE(51) / 10,
138 |
139 | hz: packet.payload.readUInt16LE(57) / 100,
140 |
141 | },
142 | inverter: {
143 | radiator_temp_celsius: packet.payload.readInt16LE(63) / 100, //TODO: is this actually a signed int?
144 | },
145 | inverter_meta: {
146 | rated_power_w: packet.payload.readUInt16BE(129) / 10,
147 | mppt_count: packet.payload.readInt8(131),
148 | phase_count: packet.payload.readInt8(132),
149 |
150 | startup_self_check_time: packet.payload.readUInt16BE(243),
151 | current_time: Protocol.parseTime(packet.payload.subarray(245, 251)),
152 |
153 |
154 | grid_freq_hz_overfreq_load_reduction_starting_point: packet.payload.readUInt16BE(223) / 100,
155 | grid_overfreq_load_reduction_percent: packet.payload.readUInt16BE(225),
156 |
157 | grid_v_limit_upper: packet.payload.readUInt16BE(235) / 10,
158 | grid_v_limit_lower: packet.payload.readUInt16BE(237) / 10,
159 | grid_freq_hz_limit_upper: packet.payload.readUInt16BE(239) / 100,
160 | grid_freq_hz_limit_lower: packet.payload.readUInt16BE(241) / 100,
161 |
162 | protocol_ver: packet.payload.subarray(101, 109).toString("ascii"),
163 | dc_master_fw_ver: packet.payload.subarray(109, 117).toString("ascii"),
164 | ac_fw_ver: packet.payload.subarray(117, 125).toString("ascii"),
165 | },
166 |
167 | //for some reason everything after byte ~120 is all BE compared to the above?
168 |
169 | };
170 | }
171 |
172 | static parseLoggerPacketPayload(packet) {
173 | //TODO: there's a lot more in this packet
174 | return {
175 | fw_ver: truncateToNullTerminator(packet.payload.subarray(19, 60).toString("ascii")),
176 | ip: truncateToNullTerminator(packet.payload.subarray(65, 82).toString("ascii")),
177 | ver: truncateToNullTerminator(packet.payload.subarray(89, 130).toString("ascii")), //hw revision maybe?
178 | ssid: truncateToNullTerminator(packet.payload.subarray(172, 210).toString("ascii")),
179 | };
180 | }
181 |
182 | static buildTimeResponse(packet) {
183 | const response = Buffer.alloc(23);
184 |
185 | // header
186 | response[0] = 0xa5; //magic
187 | response.writeUInt16LE(10, 1); //payload len
188 | response[3] = packet.header.unknown1;
189 | response[4] = packet.header.type - 0x30; // set type to response for that type
190 | response[5] = packet.header.msgIDResponse + 1;
191 | response[6] = packet.header.msgIDRequest;
192 | response.writeUint32LE(packet.header.loggerSerial, 7);
193 | // end header
194 |
195 | response[11] = packet.payload[0];
196 | response[12] = 0x01;
197 |
198 | response.writeUint32LE(
199 | Math.round(Date.now()/1000),
200 | 13
201 | );
202 | response.writeUint32LE(
203 | 0,
204 | 17
205 | );
206 |
207 |
208 | response[response.length - 2] = Protocol.checksum(response);
209 | response[response.length - 1] = 0x15; //magic
210 |
211 | return response;
212 | }
213 |
214 | static parseTime(buf) {
215 | return new Date(
216 | [
217 | `${2000 + buf[0]}-${buf[1].toString().padStart(2, "0")}-${buf[2].toString().padStart(2, "0")}T`,
218 | `${buf[3].toString().padStart(2, "0")}:${buf[4].toString().padStart(2, "0")}:${buf[5].toString().padStart(2, "0")}Z`
219 | ].join("")
220 | );
221 | }
222 | }
223 |
224 | Protocol.MESSAGE_REQUEST_TYPES = {
225 | HANDSHAKE: 0x41,
226 | DATA: 0x42,
227 | WIFI: 0x43,
228 | HEARTBEAT: 0x47,
229 | };
230 |
231 | Protocol.MESSAGE_RESPONSE_TYPES = {
232 | HANDSHAKE: 0x11,
233 | DATA: 0x12,
234 | // wifi info reply is 0x13?
235 | HEARTBEAT: 0x17,
236 | };
237 |
238 | Protocol.DATA_PACKET_SCHEMAS = {
239 | MICROINVERTER: 0x08,
240 | HYBRIDINVERTER: 0x11,
241 | RELAYMODULE: 0x13
242 | };
243 |
244 | module.exports = Protocol;
245 |
--------------------------------------------------------------------------------
/dummycloud/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2023 Sören Beye
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/dummycloud/src/MqttClient.js:
--------------------------------------------------------------------------------
1 | const Logger = require("./Logger");
2 | const mqtt = require("mqtt");
3 |
4 |
5 | class MqttClient {
6 | /**
7 | *
8 | * @param {import("./DummyCloud")} dummyCloud
9 | */
10 | constructor(dummyCloud) {
11 | this.dummyCloud = dummyCloud;
12 |
13 | this.autoconfTimestamps = {};
14 |
15 | this.dummyCloud.onHandshake((data) => {
16 | this.handleHandshake(data);
17 | });
18 | this.dummyCloud.onData((data) => {
19 | this.handleData(data);
20 | });
21 | }
22 |
23 | initialize() {
24 | const options = {
25 | clientId: `deye_dummycloud_${Math.random().toString(16).slice(2, 9)}`, // 23 characters allowed
26 | };
27 |
28 | if (process.env.MQTT_USERNAME) {
29 | options.username = process.env.MQTT_USERNAME;
30 |
31 | if (process.env.MQTT_PASSWORD) {
32 | options.password = process.env.MQTT_PASSWORD;
33 | }
34 | } else if (process.env.MQTT_PASSWORD) {
35 | // MQTT_PASSWORD is set but MQTT_USERNAME is not
36 | Logger.error("MQTT_PASSWORD is set but MQTT_USERNAME is not. MQTT_USERNAME must be set if MQTT_PASSWORD is set.");
37 | process.exit(1);
38 | }
39 |
40 | if (process.env.MQTT_CHECK_CERT) {
41 | options.rejectUnauthorized = (process.env.MQTT_CHECK_CERT !== "false");
42 | }
43 |
44 | this.client = mqtt.connect(process.env.MQTT_BROKER_URL, options);
45 |
46 | this.client.on("connect", () => {
47 | Logger.info("Connected to MQTT broker");
48 | });
49 |
50 | this.client.on("error", (e) => {
51 | if (e && e.message === "Not supported") {
52 | Logger.info("Connected to non-standard-compliant MQTT Broker.");
53 | } else {
54 | Logger.error("MQTT error:", e.toString());
55 | }
56 | });
57 |
58 | this.client.on("reconnect", () => {
59 | Logger.info("Attempting to reconnect to MQTT broker");
60 | });
61 | }
62 |
63 | handleHandshake(data) {
64 | // Nothing to see here
65 | }
66 |
67 | handleData(data) {
68 | this.ensureAutoconf(data.meta, data.header.loggerSerial.toString(), data.payload.inverter_meta.mppt_count);
69 | const baseTopic = `${MqttClient.TOPIC_PREFIX}/${data.header.loggerSerial.toString()}`;
70 |
71 | for (let i = 1; i <= data.payload.inverter_meta.mppt_count; i++) {
72 | this.client.publish(`${baseTopic}/pv/${i}/v`, data.payload.pv[`${i}`].v.toString());
73 | this.client.publish(`${baseTopic}/pv/${i}/i`, data.payload.pv[`${i}`].i.toString());
74 | this.client.publish(`${baseTopic}/pv/${i}/w`, data.payload.pv[`${i}`].w.toString());
75 | this.client.publish(
76 | `${baseTopic}/pv/${i}/kWh_today`,
77 | data.payload.pv[`${i}`].kWh_today.toString(),
78 | {retain: true}
79 | );
80 |
81 | if (data.payload.pv[`${i}`].kWh_total > 0) {
82 | this.client.publish(
83 | `${baseTopic}/pv/${i}/kWh_total`,
84 | data.payload.pv[`${i}`].kWh_total.toString(),
85 | {retain: true}
86 | );
87 | }
88 | }
89 |
90 | this.client.publish(`${baseTopic}/grid/active_power_w`, data.payload.grid.active_power_w.toString());
91 |
92 | this.client.publish(
93 | `${baseTopic}/grid/kWh_today`,
94 | data.payload.grid.kWh_today.toString(),
95 | {retain: true}
96 | );
97 | if (data.payload.grid.kWh_total > 0) {
98 | this.client.publish(
99 | `${baseTopic}/grid/kWh_total`,
100 | data.payload.grid.kWh_total.toString(),
101 | {retain: true}
102 | );
103 | }
104 | this.client.publish(`${baseTopic}/grid/v`, data.payload.grid.v.toString());
105 | this.client.publish(`${baseTopic}/grid/hz`, data.payload.grid.hz.toString());
106 |
107 | this.client.publish(`${baseTopic}/inverter/radiator_temperature`, data.payload.inverter.radiator_temp_celsius.toString());
108 |
109 |
110 | const totalDcPower = Object.values(data.payload.pv).reduce((sum, pv) => sum + pv.w, 0);
111 | const acPower = Math.abs(data.payload.grid.active_power_w);
112 | const efficiency = totalDcPower > 0 && totalDcPower > acPower ? ((acPower / totalDcPower) * 100).toFixed(2) : "null";
113 |
114 | this.client.publish(`${baseTopic}/inverter/efficiency`, efficiency);
115 | }
116 |
117 | ensureAutoconf(meta, loggerSerial, mpptCount) {
118 | // (Re-)publish every 4 hours
119 | if (Date.now() - (this.autoconfTimestamps[loggerSerial] ?? 0) <= 4 * 60 * 60 * 1000) {
120 | return;
121 | }
122 | const baseTopic = `${MqttClient.TOPIC_PREFIX}/${loggerSerial.toString()}`;
123 | const device = {
124 | "manufacturer":"Deye",
125 | "model":"Microinverter",
126 | "name":`Deye Microinverter ${loggerSerial}`,
127 | "configuration_url": `http://${meta.remoteAddress}/index_cn.html`,
128 | "identifiers":[
129 | `deye_dummycloud_${loggerSerial}`
130 | ]
131 | };
132 |
133 | for (let i = 1; i <= mpptCount; i++) {
134 | this.client.publish(
135 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_pv${i}_v/config`,
136 | JSON.stringify({
137 | "state_topic": `${baseTopic}/pv/${i}/v`,
138 | "name":`PV ${i} Voltage`,
139 | "unit_of_measurement": "V",
140 | "device_class": "voltage",
141 | "state_class": "measurement",
142 | "object_id": `deye_dummycloud_${loggerSerial}_pv_${i}_v`,
143 | "unique_id": `deye_dummycloud_${loggerSerial}_pv_${i}_v`,
144 | "expire_after": 360,
145 | "enabled_by_default": i < 3,
146 | "device": device
147 | }),
148 | {retain: true}
149 | );
150 | this.client.publish(
151 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_pv${i}_i/config`,
152 | JSON.stringify({
153 | "state_topic": `${baseTopic}/pv/${i}/i`,
154 | "name":`PV ${i} Current`,
155 | "unit_of_measurement": "A",
156 | "device_class": "current",
157 | "state_class": "measurement",
158 | "object_id": `deye_dummycloud_${loggerSerial}_pv_${i}_i`,
159 | "unique_id": `deye_dummycloud_${loggerSerial}_pv_${i}_i`,
160 | "expire_after": 360,
161 | "enabled_by_default": i < 3,
162 | "device": device
163 | }),
164 | {retain: true}
165 | );
166 | this.client.publish(
167 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_pv${i}_w/config`,
168 | JSON.stringify({
169 | "state_topic": `${baseTopic}/pv/${i}/w`,
170 | "name":`PV ${i} Power`,
171 | "unit_of_measurement": "W",
172 | "device_class": "power",
173 | "state_class": "measurement",
174 | "object_id": `deye_dummycloud_${loggerSerial}_pv_${i}_w`,
175 | "unique_id": `deye_dummycloud_${loggerSerial}_pv_${i}_w`,
176 | "expire_after": 360,
177 | "enabled_by_default": i < 3,
178 | "device": device
179 | }),
180 | {retain: true}
181 | );
182 |
183 | this.client.publish(
184 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_pv${i}_kWh_today/config`,
185 | JSON.stringify({
186 | "state_topic": `${baseTopic}/pv/${i}/kWh_today`,
187 | "name":`PV ${i} Energy Today`,
188 | "unit_of_measurement": "kWh",
189 | "device_class": "energy",
190 | "state_class": "total_increasing",
191 | "object_id": `deye_dummycloud_${loggerSerial}_pv_${i}_kWh_today`,
192 | "unique_id": `deye_dummycloud_${loggerSerial}_pv_${i}_kWh_today`,
193 | "enabled_by_default": i < 3,
194 | "device": device
195 | }),
196 | {retain: true}
197 | );
198 | this.client.publish(
199 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_pv${i}_kWh_total/config`,
200 | JSON.stringify({
201 | "state_topic": `${baseTopic}/pv/${i}/kWh_total`,
202 | "name":`PV ${i} Energy Total`,
203 | "unit_of_measurement": "kWh",
204 | "device_class": "energy",
205 | "state_class": "total_increasing",
206 | "object_id": `deye_dummycloud_${loggerSerial}_pv_${i}_kWh_total`,
207 | "unique_id": `deye_dummycloud_${loggerSerial}_pv_${i}_kWh_total`,
208 | "enabled_by_default": i < 3,
209 | "device": device
210 | }),
211 | {retain: true}
212 | );
213 | }
214 |
215 |
216 | this.client.publish(
217 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_grid_active_power_w/config`,
218 | JSON.stringify({
219 | "state_topic": `${baseTopic}/grid/active_power_w`,
220 | "name":"Grid Power (Active)",
221 | "unit_of_measurement": "W",
222 | "device_class": "power",
223 | "state_class": "measurement",
224 | "object_id": `deye_dummycloud_${loggerSerial}_grid_active_power_w`,
225 | "unique_id": `deye_dummycloud_${loggerSerial}_grid_active_power_w`,
226 | "expire_after": 360,
227 | "device": device
228 | }),
229 | {retain: true}
230 | );
231 | this.client.publish(
232 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_grid_kWh_today/config`,
233 | JSON.stringify({
234 | "state_topic": `${baseTopic}/grid/kWh_today`,
235 | "name":"Grid Energy Today",
236 | "unit_of_measurement": "kWh",
237 | "device_class": "energy",
238 | "state_class": "total_increasing",
239 | "object_id": `deye_dummycloud_${loggerSerial}_grid_energy_today`,
240 | "unique_id": `deye_dummycloud_${loggerSerial}_grid_energy_today`,
241 | "device": device
242 | }),
243 | {retain: true}
244 | );
245 | this.client.publish(
246 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_grid_kWh_total/config`,
247 | JSON.stringify({
248 | "state_topic": `${baseTopic}/grid/kWh_total`,
249 | "name":"Grid Energy Total",
250 | "unit_of_measurement": "kWh",
251 | "device_class": "energy",
252 | "state_class": "total_increasing",
253 | "object_id": `deye_dummycloud_${loggerSerial}_grid_energy_total`,
254 | "unique_id": `deye_dummycloud_${loggerSerial}_grid_energy_total`,
255 | "device": device
256 | }),
257 | {retain: true}
258 | );
259 | this.client.publish(
260 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_grid_v/config`,
261 | JSON.stringify({
262 | "state_topic": `${baseTopic}/grid/v`,
263 | "name":"Grid Voltage",
264 | "unit_of_measurement": "V",
265 | "device_class": "voltage",
266 | "state_class": "measurement",
267 | "object_id": `deye_dummycloud_${loggerSerial}_grid_v`,
268 | "unique_id": `deye_dummycloud_${loggerSerial}_grid_v`,
269 | "expire_after": 360,
270 | "device": device
271 | }),
272 | {retain: true}
273 | );
274 | this.client.publish(
275 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_grid_hz/config`,
276 | JSON.stringify({
277 | "state_topic": `${baseTopic}/grid/hz`,
278 | "name":"Grid Frequency",
279 | "unit_of_measurement": "Hz",
280 | "device_class": "frequency",
281 | "state_class": "measurement",
282 | "object_id": `deye_dummycloud_${loggerSerial}_grid_hz`,
283 | "unique_id": `deye_dummycloud_${loggerSerial}_grid_hz`,
284 | "expire_after": 360,
285 | "device": device
286 | }),
287 | {retain: true}
288 | );
289 |
290 | this.client.publish(
291 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_inverter_radiator_temperature/config`,
292 | JSON.stringify({
293 | "state_topic": `${baseTopic}/inverter/radiator_temperature`,
294 | "name":"Radiator Temperature",
295 | "unit_of_measurement": "°C",
296 | "device_class": "temperature",
297 | "state_class": "measurement",
298 | "object_id": `deye_dummycloud_${loggerSerial}_inverter_radiator_temperature`,
299 | "unique_id": `deye_dummycloud_${loggerSerial}_inverter_radiator_temperature`,
300 | "expire_after": 360,
301 | "device": device
302 | }),
303 | {retain: true}
304 | );
305 |
306 | this.client.publish(
307 | `homeassistant/sensor/deye_dummycloud_${loggerSerial}/${loggerSerial}_inverter_efficiency/config`,
308 | JSON.stringify({
309 | "state_topic": `${baseTopic}/inverter/efficiency`,
310 | "name":"Inverter Efficiency",
311 | "unit_of_measurement": "%",
312 | "entity_category": "diagnostic",
313 | "icon": "mdi:cog-transfer",
314 | "state_class": "measurement",
315 | "object_id": `deye_dummycloud_${loggerSerial}_inverter_efficiency`,
316 | "unique_id": `deye_dummycloud_${loggerSerial}_inverter_efficiency`,
317 | "expire_after": 360,
318 | "value_template": "{{ value_json }}",
319 | "device": device
320 | }),
321 | {retain: true}
322 | );
323 |
324 | this.autoconfTimestamps[loggerSerial] = Date.now();
325 | }
326 | }
327 |
328 | MqttClient.TOPIC_PREFIX = "deye-dummycloud";
329 |
330 | module.exports = MqttClient;
331 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Deye Microinverter - Cloud-free
2 |
3 | 
4 |
5 | Solar power generation work best if there are no clouds anywhere to be seen :)
6 |
7 |
8 | This repository aims to document how to use Deye microinverters entirely local only and cloud free.
9 | It consolidates the knowledge that at the time of writing was spread over hundreds of different posts, issues and comments.
10 |
11 | Furthermore, it also features a cloud replacement implementation so you won't have to install any apps or create any accounts.
12 | You also won't have to share any e-mail address or phone number.
13 |
14 | ## Devices
15 |
16 | So far, the following devices are known to work like this:
17 |
18 | - Deye SUN600G3-EU-230
19 | - Deye SUN-M80G3-EU-Q0
20 | - Deye SUN-M80G4-EU-Q0
21 |
22 | it should also be the same for other inverters of the same series including rebrands such as Bosswerk.
23 | If you have verified that it works with another device, feel free to extend this list.
24 |
25 | ## TL;DR
26 |
27 | Here are the main things you will want to know about these microinverters:
28 |
29 | - They have Wi-Fi
30 | - They can be connected to Wi-Fi networks via their webinterface
31 | - They can operate without an internet connection
32 | - They can operate without an account
33 | - They can be monitored and controlled via their local ModbusTCP interface
34 | - You can also completely replace the cloud with a local implementation: [dummycloud](./dummycloud)
35 |
36 | **2024-08-20 Update**
37 |
38 | Deye has started rolling out firmware updates for the logger that block both ModbusTCP access and prevent the mock cloud
39 | from working due to the introduction of TLS. Fortunately, for now it seems that newly bought inverters still come with older
40 | logger firmwares that work offline.
41 | Also equally fortunately, it seems that downgrading the firmware is possible as well.
42 |
43 | However, both of these things may change in the future.
44 |
45 | ## Preamble
46 |
47 | Compared to traditional PV setups where a single large inverter is connected to strings of many PV Panels, in a microinverter Setup, you have one small inverter for every 1-4 PV Panels.
48 |
49 | There are up- and downsides to both of these topologies but that is for now out of scope for this document.
50 | What you need to know is that microinverters are cheaper and scaled-down versions of their larger brothers.
51 |
52 | Because they only cost 150-200€ they make getting into solar power generation accessible for many more people than ever before.
53 | Paired with two PV Panels you're looking at an investment of at most 1000€ to get free energy from the sun.
54 |
55 | Additionally, because you only need few panels for the setup to make sense financially, often a balcony or garden can be enough for a small solar setup.
56 | This is especially interesting for people living in rental properties.
57 |
58 | ### Word of warning
59 |
60 | After reading through way too many concerning posts and comments, here's what has to be said:
61 |
62 | **Please** please please don't cut any corners when it comes to safety-critical stuff such as cabling and also mounting panels.
63 | You don't want your home to burn down or anyone to be killed by a falling 1.5m² 25kg PV Panel.
64 |
65 | Electricity is dangerous. So are heavy things with a huge attack surface for wind.
66 | When in doubt, contact a local electrician. They know what they're doing and will help you.
67 |
68 | ## Setup
69 |
70 | Now with that out of the way, we can talk about what to do.
71 |
72 | The first important thing to note is that these inverters will shut down if they don't sense at least 20V on at least one PV input.
73 | This means that you have to do all this during the day connected while connected to a PV panel.
74 |
75 | Alternatively, some people reported that they got the inverter to wake up by connecting a 30V lab power supply to one of the PV inputs.
76 |
77 | ### Joining Wi-Fi
78 |
79 | By default, your microinverter should provide a Wi-Fi Access point with an SSID named similarly to `AP_4151234567`.
80 | Using a laptop, connect to that using the password printed on the AP or for older inverters the default password `12345678`.
81 |
82 | In a browser, navigate to the IP of the inverter in that network which should by default be `http://10.10.100.254/`.
83 | Log in to the webinterface with the default credentials `admin:admin` and use that to configure Wi-Fi.
84 |
85 | 
86 |
87 | The AP-mode can be a bit unstable so prepare for the webinterface stopping to work occasionally.
88 | Once the inverter is connected to you Wi-Fi, this should not be an issue anymore.
89 |
90 |
91 | ### Ensuring a patched logger firmware
92 |
93 | After joining the inverter to you Wi-Fi network, connect to the webinterface again but this time using the IP in your network.
94 |
95 | Now, expand the `Device Information` on the `Status` page and ensure that your logger firmware version is at least `MW3_16U_5406_1.53` or newer.
96 |
97 | 
98 |
99 | Older firmwares don't allow reconfiguration of the Wi-Fi AP, which is a serious vulnerability, as it allows an attacker to easily gain access to your real Wi-Fi credentials.
100 |
101 | If your firmware is older, you can find firmware update files in this repo: [https://github.com/dasrecht/deye-firmware](https://github.com/dasrecht/deye-firmware).
102 | You can flash them using the `Upgrade Firmware` page of the webinterface.
103 |
104 |
105 | ### Securing the AP
106 |
107 | With the logger firmware upgraded, you should now use the webinterface to change SSID and Password for the AP of the inverter.
108 |
109 | 
110 |
111 | Pick something not immediately obvious and relatively secure as - as mentioned before - it is all that prevents an attacker from connecting to that AP and reading out your main Wi-Fi credentials.
112 |
113 | I have been told that you can also use the wizard to disable the AP entirely, however personally, I like having a fallback way into the inverter, especially since I did not see a "Factory Reset" button on the device.
114 |
115 |
116 | ### Configuring your network
117 |
118 | Now that the AP is secured, use the configuration interface of your router to block internet access of the inverter.
119 | You will also likely want to configure it, so that it will always get the same IP assigned via DHCP.
120 |
121 | These things should be dropdowns and checkboxes in most consumer routers.
122 | If you run some advanced setup, you will know what to do.
123 |
124 | You can also try to DNS-block `access1.solarmanpv.com` and `access2.solarmanpv.com`, however it seems that the logger firmware might also use hardcoded IPs?
125 | Either way, just blocking internet access entirely should be much easier in most setups anyway and comes with no known downsides.
126 |
127 | ## Usage
128 |
129 | After connecting the inverter to your Wi-Fi network, securing it and blocking its internet access, all you need to do now is monitor and control it.
130 |
131 | For this there are different options.
132 |
133 | ### Local polling
134 | Most of the options rely on polling the local modbusTCP interface that uses the inverter logger serial number for authentication.
135 |
136 | To get this serial, simply look at the sticker on the device:
137 |
138 | 
139 |
140 | If you feel like doing something arcane and/or want to build something for that yourself, you can find the Modbus spec for these inverters in the complementary assets repo:
141 | [https://github.com/Hypfer/deye-microinverter-cloud-free-assets](https://github.com/Hypfer/deye-microinverter-cloud-free-assets).
142 |
143 | Note that with internet access blocked, the inverter never receives any time information.
144 | This breaks the `Yield today` counter as it will never properly reset unless you manually set the time on each boot using modbus register `22`, `23` and `24`.
145 |
146 |
147 | #### With Home Assistant
148 |
149 | With Home Assistant, the easiest way to get your inverter connected is by using [HACS](https://hacs.xyz/) to install the [Solarman](https://github.com/StephanJoubert/home_assistant_solarman) `custom_component`.
150 | Please refer to the project documentation on how to install and configure those.
151 |
152 | Home Assistant offers powerful tooling to store, visualize and process data right out of the box.
153 |
154 | For example, here's how a solar dashboard could look like using mock data and only stock home assistant cards.
155 | The real world will obviously look slightly different but the idea should be the same:
156 |
157 | 
158 |
159 |
160 | #### With other smarthome software
161 |
162 | If you're using OpenHAB, FHEM, ioBroker or something else, as long as it can speak MQTT, you can use for example [https://github.com/kbialek/deye-inverter-mqtt](https://github.com/kbialek/deye-inverter-mqtt) to connect your inverter to your smarthome.
163 |
164 | A `docker-compose.yml` entry for that tool could look like this:
165 |
166 | ```yaml
167 | deyetomqtt:
168 | image: ghcr.io/kbialek/deye-inverter-mqtt
169 | container_name: "deyetomqtt"
170 | environment:
171 | - LOG_LEVEL=DEBUG
172 | - DEYE_DATA_READ_INTERVAL=60
173 | - DEYE_METRIC_GROUPS=micro
174 | - DEYE_LOGGER_SERIAL_NUMBER=4151234567
175 | - DEYE_LOGGER_IP_ADDRESS=192.168.178.123
176 | - DEYE_LOGGER_PORT=8899
177 | - MQTT_HOST=192.168.178.2
178 | - MQTT_TOPIC_PREFIX=deye
179 | - MQTT_PORT=1883
180 | restart: always
181 | ```
182 |
183 | Keep in mind that this might change in the future so make sure to always check the docs of the project itself.
184 |
185 | ### Using the dummycloud
186 |
187 | If you don't want polling and/or are unhappy with having the inverter in a perpetual state of reconnection to the cloud,
188 | you can instead deploy the cloud replacement that can be found in the [dummycloud](./dummycloud) folder in this repository.
189 |
190 | This will make the inverter happy, provide it with the correct time for daily counters to work and push all the data to your MQTT broker.
191 | It will also autoconfigure entities for home assistant.
192 |
193 | 
194 |
195 | It is however a bit more complicated than the polling approaches, as it requires you to understand how networks work
196 | and how to deploy a service somewhere. Nothing too arcane of course but if you don't know anything about linux, you might want to pass on this.
197 |
198 | For further information, check out the [dummycloud](./dummycloud) folder.
199 |
200 | ## Misc
201 |
202 | ### Hidden configuration page
203 |
204 | These inverters also have a hidden configuration page that is reachable via `/config_hide.html`.
205 |
206 | There, it is possible to configure
207 |
208 | - Cloud Server A and B
209 | - Serial Port parameters (which serial port?)
210 | - The port of the modbusTCP server of the inverter
211 | - Enable/Disable the AP
212 | - Switch the branding(?)
213 |
214 |
215 | Click here to show a screenshot of the page
216 |
217 | 
218 |
219 |
220 |
221 | ### AT Commands
222 |
223 | Apart from the modbus over tcp interface, these inverters also provide another interface on port 48899 where you can talk to it over AT commands like a modem.
224 | For that, for now you can use this tool: [https://github.com/s10l/deye-logger-at-cmd](https://github.com/s10l/deye-logger-at-cmd).
225 |
226 | Some firmware versions seem to respond to the `AT+H` command with a full list of commands.
227 | Mine doesn't, however a [user fortunately posted a full response](https://www.photovoltaikforum.com/thread/180129-deye-sun600-und-sun2000-erfahrungen/?postID=2846951#post2846951) which is the source for this table:
228 |
229 |
230 | Click here to show the AT command table
231 |
232 | | Command | Vendor Description |
233 | |-------------------------------------------|---------------------------------------------------------|
234 | | AT+TIME | Set/Get Device Time |
235 | | AT+ADDRESS | Set/Get Device Address |
236 | | AT+KEY | Set/Get Device Password |
237 | | AT+MTYPE | Set/Get Device Mtype |
238 | | AT+CNMOSAVE | Set/Get TCPB Link Mode |
239 | | AT+DEVICENUM | Set/Get Device Link Num |
240 | | AT+DEVSELCTL | Set/Get Web Device List Info |
241 | | AT+NDBGS | Set/Get Debug Status |
242 | | AT+FFCLER | Clear File in Flash |
243 | | AT+LANGSEL | Select Language |
244 | | AT+ADTIME | Set/Get Device Time |
245 | | AT+YZFTIME | Set/Get Device factory Time |
246 | | AT+TZEARSE | Clear yz File in Flash |
247 | | AT+YZACK | Clear yz File in Flash |
248 | | AT+YZTIME | Clear yz File in Flash |
249 | | AT+YZWKTIME | Clear yz File in Flash |
250 | | AT+YZERRCLR | Clear yz File in Flash |
251 | | AT+YZDBNUM | Clear yz File in Flash |
252 | | AT+YZDB | Clear yz File in Flash |
253 | | AT+YZVER | Clear yz File in Flash |
254 | | AT+YZLOG | Clear yz File in Flash |
255 | | AT+YZAPP | Clear yz File in Flash |
256 | | AT+YZAPSTAT | Clear yz File in Flash |
257 | | AT+YZsize | Clear yz File in Flash |
258 | | AT+YZsize | Clear yz File in Flash |
259 | | AT+YZsize | Clear yz File in Flash |
260 | | AT+YZsize | Clear yz File in Flash |
261 | | AT+YZsize | Clear yz File in Flash |
262 | | AT+YZsize | Clear yz File in Flash |
263 | | AT+YZsize | Clear yz File in Flash |
264 | | AT+YZWAKEYCTL | Clear yz File in Flash |
265 | | AT+YZsize | Clear yz File in Flash |
266 | | AT+YZFLSHTEST=, | |
267 | | AT+YZFLSHTEST=, | |
268 | | AT+YZVER | Clear yz File in Flash |
269 | | AT+YZVER | Clear yz File in Flash |
270 | | AT+YZVER | Clear yz File in Flash |
271 | | AT+YZVER | Clear yz File in Flash |
272 | | AT+YZVER | Clear yz File in Flash |
273 | | AT+YZEXPFUN | Clear yz File in Flash |
274 | | AT+YZEXPFUN | Clear yz File in Flash |
275 | | AT+YZEXPFUN | Clear yz File in Flash |
276 | | AT+YZEXPFUN | Clear yz File in Flash |
277 | | AT+YZEXPFUN | Clear yz File in Flash |
278 | | AT+YZEXPFUN | Clear yz File in Flash |
279 | | AT+TMODE | Set/Get the UART work mode. |
280 | | AT+ENTM | Goto Through MOde. |
281 | | AT+UART | Set/Get the UART0/UART1 Parameters. |
282 | | AT+WSMAC | Set/Get Module MAC Address. |
283 | | AT+WAMAC | Get Module MAC Address in AP mode. |
284 | | AT+NDBGL | set/get debug level |
285 | | AT+RELD | Reload the default setting and reboot. |
286 | | AT+RLDEN | Put on/off the Reload Pin. |
287 | | AT+MID | Get The Module ID. |
288 | | AT+WRMID | Write Module ID. |
289 | | AT+ASWD | Set/Query WiFi configuration code. |
290 | | AT+VER | Get application version. |
291 | | AT+BVER | Get bootloader version. |
292 | | AT+HWVER | Get hardware version. |
293 | | AT+FCLR | Clear Fsetting. |
294 | | AT+CFGRD | Get current system config. |
295 | | AT+CFGTF | Save Current Config to Default Config. |
296 | | AT+SMEM | show system memory stat |
297 | | AT+OTA | OTA |
298 | | AT+UPURL | Set/Get the path of remote upgrade. |
299 | | AT+CMDPW | Set/Get cmd password in throuphput mode. |
300 | | AT+UID | Set/Get UID. |
301 | | AT+E | Echo ON/Off, to turn on/off command line echo function. |
302 | | AT+Z | Reset the Module. |
303 | | AT+SRST | Soft Reset the Module. |
304 | | AT+H | show help |
305 | | AT+NETP | Set/Get the Net Protocol Parameters. |
306 | | AT+TCPLK | Get The state of TCP link. |
307 | | AT+TCPTO | Set/Get TCP time out. |
308 | | AT+TCPDIS | Connect/Dis-connect the TCP Client link |
309 | | AT+MAXSK | Set/Get MAX num of TCP socket (1~5) |
310 | | AT+RCV | Recv data from socket_a |
311 | | AT+SEND | Send data to socket_a |
312 | | AT+SOCKB | Set/Get Parameters of socket_b. |
313 | | AT+TCPLKB | Get The state of TCP_B link. |
314 | | AT+TCPTOB | Set/Get TCP_B time out. |
315 | | AT+TCPDISB | Connect/Dis-connect the TCP_B Client link. |
316 | | AT+RCVB | Recv data from socket_b |
317 | | AT+SNDB | Send data to socket_b |
318 | | AT+WMODE | Set/Get the WIFI Operation Mode (AP or STA). |
319 | | AT+WSSSID | Set/Get the AP's SSID of WIFI STA Mode. |
320 | | AT+WSKEY | Set/Get the Security Parameters of WIFI STA Mode. |
321 | | AT+WSLK | Get Link Status of the Module (Only for STA Mode). |
322 | | AT+WSLQ | Get Link Quality of the Module (Only for STA Mode). |
323 | | AT+WAP | Set/Get the AP parameters. |
324 | | AT+WAKEY | Set/Get the Security Parameters of WIFI AP Mode. |
325 | | AT+WALK | Show sta information of AP connection. |
326 | | AT+WALKIND | enable/disable LED indication of AP connection. |
327 | | AT+WAPMXSTA | Set/Get the Max Number Of Sta Connected to Ap. |
328 | | AT+WSCAN | Get The AP site Survey (only for STA Mode). |
329 | | AT+SMTLK | Start Smart Configuration. |
330 | | AT+SMTLKST=mode,protocol | Setup smartlnk mode and protocol. |
331 | | AT+SMARTAPCONFIG | Enable/disable smart AP config function. |
332 | | AT+SMARTAPSTART | Start smart AP config function. |
333 | | AT+WPS | Start WPS. |
334 | | AT+DISPS | Disable power saving mode of WIFI |
335 | | AT+WIFI=UP/DOWN | Power down or up the wifi chip. |
336 | | AT+MDCH | Put on/off automatic switching WIFI mode. |
337 | | AT+WSLKO | Enable/Disable connect router with the best signal. |
338 | | AT+DTIM | Set/Get station listen interval(1~3). |
339 | | AT+UDPLCPT | Set/Get local UDP port. |
340 | | AT+PING | General PING command. |
341 | | AT+WANN | Set/Get The WAN setting if in STA mode. |
342 | | AT+LANN | Set/Get The LAN setting if in ADHOC mode. |
343 | | AT+WADHCP | enable/disable AP dhcp server and set ip address pool |
344 | | AT+WEBU | Set/Get the Login Parameters of WEB page. |
345 | | AT+WEBVER | Get WEB version. |
346 | | AT+PLANG=EN/CN | Set/Get the language of WEB page. |
347 | | AT+WSDNS | Set/Get the DNS Server address. |
348 | | AT+NTPEN | Enable/Disable NTP Server. |
349 | | AT+NTPRF | Set/Query NTP. |
350 | | AT+NTPTM | Set/Query Ntp Time. |
351 | | AT+NTPSER | Set/Query Ntp Server. |
352 | | AT+TXPWR | Set/Get wifi rf tx power. |
353 | | AT+RFTESTMODE | RF test mode ON/OFF. |
354 |
355 |
356 |
357 |
358 | ## Donate
359 |
360 | If this software and documentation effort brought value to you, there's the option to leave a small donation using the "Sponsor" button on top of the repo or by [clicking right here](https://github.com/sponsors/Hypfer).
361 |
362 | Thanks!
363 |
--------------------------------------------------------------------------------
/dummycloud/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deye-dummycloud",
3 | "version": "1.1.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "deye-dummycloud",
9 | "version": "1.1.0",
10 | "license": "Apache-2.0",
11 | "dependencies": {
12 | "mqtt": "^4.3.7"
13 | },
14 | "devDependencies": {
15 | "eslint": "8.16.0",
16 | "eslint-plugin-jsdoc": "48.9.3",
17 | "eslint-plugin-regexp": "1.7.0",
18 | "eslint-plugin-sort-keys-fix": "1.1.2",
19 | "eslint-plugin-sort-requires": "git+https://npm@github.com/Hypfer/eslint-plugin-sort-requires.git#2.1.1"
20 | }
21 | },
22 | "node_modules/@aashutoshrathi/word-wrap": {
23 | "version": "1.2.6",
24 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
25 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
26 | "dev": true,
27 | "engines": {
28 | "node": ">=0.10.0"
29 | }
30 | },
31 | "node_modules/@es-joy/jsdoccomment": {
32 | "version": "0.46.0",
33 | "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz",
34 | "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==",
35 | "dev": true,
36 | "dependencies": {
37 | "comment-parser": "1.4.1",
38 | "esquery": "^1.6.0",
39 | "jsdoc-type-pratt-parser": "~4.0.0"
40 | },
41 | "engines": {
42 | "node": ">=16"
43 | }
44 | },
45 | "node_modules/@eslint/eslintrc": {
46 | "version": "1.4.1",
47 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
48 | "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
49 | "dev": true,
50 | "dependencies": {
51 | "ajv": "^6.12.4",
52 | "debug": "^4.3.2",
53 | "espree": "^9.4.0",
54 | "globals": "^13.19.0",
55 | "ignore": "^5.2.0",
56 | "import-fresh": "^3.2.1",
57 | "js-yaml": "^4.1.0",
58 | "minimatch": "^3.1.2",
59 | "strip-json-comments": "^3.1.1"
60 | },
61 | "engines": {
62 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
63 | },
64 | "funding": {
65 | "url": "https://opencollective.com/eslint"
66 | }
67 | },
68 | "node_modules/@humanwhocodes/config-array": {
69 | "version": "0.9.5",
70 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
71 | "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
72 | "dev": true,
73 | "dependencies": {
74 | "@humanwhocodes/object-schema": "^1.2.1",
75 | "debug": "^4.1.1",
76 | "minimatch": "^3.0.4"
77 | },
78 | "engines": {
79 | "node": ">=10.10.0"
80 | }
81 | },
82 | "node_modules/@humanwhocodes/object-schema": {
83 | "version": "1.2.1",
84 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
85 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
86 | "dev": true
87 | },
88 | "node_modules/@pkgr/core": {
89 | "version": "0.1.1",
90 | "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
91 | "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
92 | "dev": true,
93 | "engines": {
94 | "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
95 | },
96 | "funding": {
97 | "url": "https://opencollective.com/unts"
98 | }
99 | },
100 | "node_modules/acorn": {
101 | "version": "8.12.1",
102 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
103 | "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
104 | "dev": true,
105 | "bin": {
106 | "acorn": "bin/acorn"
107 | },
108 | "engines": {
109 | "node": ">=0.4.0"
110 | }
111 | },
112 | "node_modules/acorn-jsx": {
113 | "version": "5.3.2",
114 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
115 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
116 | "dev": true,
117 | "peerDependencies": {
118 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
119 | }
120 | },
121 | "node_modules/ajv": {
122 | "version": "6.12.6",
123 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
124 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
125 | "dev": true,
126 | "dependencies": {
127 | "fast-deep-equal": "^3.1.1",
128 | "fast-json-stable-stringify": "^2.0.0",
129 | "json-schema-traverse": "^0.4.1",
130 | "uri-js": "^4.2.2"
131 | },
132 | "funding": {
133 | "type": "github",
134 | "url": "https://github.com/sponsors/epoberezkin"
135 | }
136 | },
137 | "node_modules/ansi-regex": {
138 | "version": "5.0.1",
139 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
140 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
141 | "dev": true,
142 | "engines": {
143 | "node": ">=8"
144 | }
145 | },
146 | "node_modules/ansi-styles": {
147 | "version": "4.3.0",
148 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
149 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
150 | "dev": true,
151 | "dependencies": {
152 | "color-convert": "^2.0.1"
153 | },
154 | "engines": {
155 | "node": ">=8"
156 | },
157 | "funding": {
158 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
159 | }
160 | },
161 | "node_modules/are-docs-informative": {
162 | "version": "0.0.2",
163 | "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
164 | "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
165 | "dev": true,
166 | "engines": {
167 | "node": ">=14"
168 | }
169 | },
170 | "node_modules/argparse": {
171 | "version": "2.0.1",
172 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
173 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
174 | "dev": true
175 | },
176 | "node_modules/balanced-match": {
177 | "version": "1.0.2",
178 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
179 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
180 | },
181 | "node_modules/base64-js": {
182 | "version": "1.5.1",
183 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
184 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
185 | "funding": [
186 | {
187 | "type": "github",
188 | "url": "https://github.com/sponsors/feross"
189 | },
190 | {
191 | "type": "patreon",
192 | "url": "https://www.patreon.com/feross"
193 | },
194 | {
195 | "type": "consulting",
196 | "url": "https://feross.org/support"
197 | }
198 | ]
199 | },
200 | "node_modules/bl": {
201 | "version": "4.1.0",
202 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
203 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
204 | "dependencies": {
205 | "buffer": "^5.5.0",
206 | "inherits": "^2.0.4",
207 | "readable-stream": "^3.4.0"
208 | }
209 | },
210 | "node_modules/brace-expansion": {
211 | "version": "1.1.11",
212 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
213 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
214 | "dependencies": {
215 | "balanced-match": "^1.0.0",
216 | "concat-map": "0.0.1"
217 | }
218 | },
219 | "node_modules/buffer": {
220 | "version": "5.7.1",
221 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
222 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
223 | "funding": [
224 | {
225 | "type": "github",
226 | "url": "https://github.com/sponsors/feross"
227 | },
228 | {
229 | "type": "patreon",
230 | "url": "https://www.patreon.com/feross"
231 | },
232 | {
233 | "type": "consulting",
234 | "url": "https://feross.org/support"
235 | }
236 | ],
237 | "dependencies": {
238 | "base64-js": "^1.3.1",
239 | "ieee754": "^1.1.13"
240 | }
241 | },
242 | "node_modules/buffer-from": {
243 | "version": "1.1.2",
244 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
245 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
246 | },
247 | "node_modules/callsites": {
248 | "version": "3.1.0",
249 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
250 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
251 | "dev": true,
252 | "engines": {
253 | "node": ">=6"
254 | }
255 | },
256 | "node_modules/chalk": {
257 | "version": "4.1.2",
258 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
259 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
260 | "dev": true,
261 | "dependencies": {
262 | "ansi-styles": "^4.1.0",
263 | "supports-color": "^7.1.0"
264 | },
265 | "engines": {
266 | "node": ">=10"
267 | },
268 | "funding": {
269 | "url": "https://github.com/chalk/chalk?sponsor=1"
270 | }
271 | },
272 | "node_modules/color-convert": {
273 | "version": "2.0.1",
274 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
275 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
276 | "dev": true,
277 | "dependencies": {
278 | "color-name": "~1.1.4"
279 | },
280 | "engines": {
281 | "node": ">=7.0.0"
282 | }
283 | },
284 | "node_modules/color-name": {
285 | "version": "1.1.4",
286 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
287 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
288 | "dev": true
289 | },
290 | "node_modules/comment-parser": {
291 | "version": "1.4.1",
292 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
293 | "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
294 | "dev": true,
295 | "engines": {
296 | "node": ">= 12.0.0"
297 | }
298 | },
299 | "node_modules/commist": {
300 | "version": "1.1.0",
301 | "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
302 | "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
303 | "dependencies": {
304 | "leven": "^2.1.0",
305 | "minimist": "^1.1.0"
306 | }
307 | },
308 | "node_modules/concat-map": {
309 | "version": "0.0.1",
310 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
311 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
312 | },
313 | "node_modules/concat-stream": {
314 | "version": "2.0.0",
315 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
316 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
317 | "engines": [
318 | "node >= 6.0"
319 | ],
320 | "dependencies": {
321 | "buffer-from": "^1.0.0",
322 | "inherits": "^2.0.3",
323 | "readable-stream": "^3.0.2",
324 | "typedarray": "^0.0.6"
325 | }
326 | },
327 | "node_modules/cross-spawn": {
328 | "version": "7.0.3",
329 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
330 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
331 | "dev": true,
332 | "dependencies": {
333 | "path-key": "^3.1.0",
334 | "shebang-command": "^2.0.0",
335 | "which": "^2.0.1"
336 | },
337 | "engines": {
338 | "node": ">= 8"
339 | }
340 | },
341 | "node_modules/debug": {
342 | "version": "4.3.7",
343 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
344 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
345 | "dependencies": {
346 | "ms": "^2.1.3"
347 | },
348 | "engines": {
349 | "node": ">=6.0"
350 | },
351 | "peerDependenciesMeta": {
352 | "supports-color": {
353 | "optional": true
354 | }
355 | }
356 | },
357 | "node_modules/deep-is": {
358 | "version": "0.1.4",
359 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
360 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
361 | "dev": true
362 | },
363 | "node_modules/doctrine": {
364 | "version": "3.0.0",
365 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
366 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
367 | "dev": true,
368 | "dependencies": {
369 | "esutils": "^2.0.2"
370 | },
371 | "engines": {
372 | "node": ">=6.0.0"
373 | }
374 | },
375 | "node_modules/duplexify": {
376 | "version": "4.1.2",
377 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz",
378 | "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
379 | "dependencies": {
380 | "end-of-stream": "^1.4.1",
381 | "inherits": "^2.0.3",
382 | "readable-stream": "^3.1.1",
383 | "stream-shift": "^1.0.0"
384 | }
385 | },
386 | "node_modules/end-of-stream": {
387 | "version": "1.4.4",
388 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
389 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
390 | "dependencies": {
391 | "once": "^1.4.0"
392 | }
393 | },
394 | "node_modules/es-module-lexer": {
395 | "version": "1.5.4",
396 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
397 | "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
398 | "dev": true
399 | },
400 | "node_modules/escape-string-regexp": {
401 | "version": "4.0.0",
402 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
403 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
404 | "dev": true,
405 | "engines": {
406 | "node": ">=10"
407 | },
408 | "funding": {
409 | "url": "https://github.com/sponsors/sindresorhus"
410 | }
411 | },
412 | "node_modules/eslint": {
413 | "version": "8.16.0",
414 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz",
415 | "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==",
416 | "dev": true,
417 | "dependencies": {
418 | "@eslint/eslintrc": "^1.3.0",
419 | "@humanwhocodes/config-array": "^0.9.2",
420 | "ajv": "^6.10.0",
421 | "chalk": "^4.0.0",
422 | "cross-spawn": "^7.0.2",
423 | "debug": "^4.3.2",
424 | "doctrine": "^3.0.0",
425 | "escape-string-regexp": "^4.0.0",
426 | "eslint-scope": "^7.1.1",
427 | "eslint-utils": "^3.0.0",
428 | "eslint-visitor-keys": "^3.3.0",
429 | "espree": "^9.3.2",
430 | "esquery": "^1.4.0",
431 | "esutils": "^2.0.2",
432 | "fast-deep-equal": "^3.1.3",
433 | "file-entry-cache": "^6.0.1",
434 | "functional-red-black-tree": "^1.0.1",
435 | "glob-parent": "^6.0.1",
436 | "globals": "^13.15.0",
437 | "ignore": "^5.2.0",
438 | "import-fresh": "^3.0.0",
439 | "imurmurhash": "^0.1.4",
440 | "is-glob": "^4.0.0",
441 | "js-yaml": "^4.1.0",
442 | "json-stable-stringify-without-jsonify": "^1.0.1",
443 | "levn": "^0.4.1",
444 | "lodash.merge": "^4.6.2",
445 | "minimatch": "^3.1.2",
446 | "natural-compare": "^1.4.0",
447 | "optionator": "^0.9.1",
448 | "regexpp": "^3.2.0",
449 | "strip-ansi": "^6.0.1",
450 | "strip-json-comments": "^3.1.0",
451 | "text-table": "^0.2.0",
452 | "v8-compile-cache": "^2.0.3"
453 | },
454 | "bin": {
455 | "eslint": "bin/eslint.js"
456 | },
457 | "engines": {
458 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
459 | },
460 | "funding": {
461 | "url": "https://opencollective.com/eslint"
462 | }
463 | },
464 | "node_modules/eslint-plugin-jsdoc": {
465 | "version": "48.9.3",
466 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.9.3.tgz",
467 | "integrity": "sha512-9RUsTlW6ZlMgy+dd9uDreU9lZAh4Hxw2ZAV5T0hPtrWgbw0OnvuT3elF6ihnpAY+NCrJx8BUUmcBnKftc/F0qw==",
468 | "dev": true,
469 | "dependencies": {
470 | "@es-joy/jsdoccomment": "~0.46.0",
471 | "are-docs-informative": "^0.0.2",
472 | "comment-parser": "1.4.1",
473 | "debug": "^4.3.5",
474 | "escape-string-regexp": "^4.0.0",
475 | "esquery": "^1.6.0",
476 | "parse-imports": "^2.1.1",
477 | "semver": "^7.6.3",
478 | "spdx-expression-parse": "^4.0.0",
479 | "synckit": "^0.9.1"
480 | },
481 | "engines": {
482 | "node": ">=18"
483 | },
484 | "peerDependencies": {
485 | "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
486 | }
487 | },
488 | "node_modules/eslint-plugin-regexp": {
489 | "version": "1.7.0",
490 | "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.7.0.tgz",
491 | "integrity": "sha512-nmhXqrEP+O+dz2z5MSkc41u/4fA8oakweoCUdfYwox7DBhzadEqZz8T+s6/UiY0NIU0kv+3UrzBfhPp4wUxbaA==",
492 | "dev": true,
493 | "dependencies": {
494 | "comment-parser": "^1.1.2",
495 | "eslint-utils": "^3.0.0",
496 | "grapheme-splitter": "^1.0.4",
497 | "jsdoctypeparser": "^9.0.0",
498 | "refa": "^0.9.0",
499 | "regexp-ast-analysis": "^0.5.1",
500 | "regexpp": "^3.2.0",
501 | "scslre": "^0.1.6"
502 | },
503 | "engines": {
504 | "node": "^12 || >=14"
505 | },
506 | "peerDependencies": {
507 | "eslint": ">=6.0.0"
508 | }
509 | },
510 | "node_modules/eslint-plugin-sort-keys-fix": {
511 | "version": "1.1.2",
512 | "resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.2.tgz",
513 | "integrity": "sha512-DNPHFGCA0/hZIsfODbeLZqaGY/+q3vgtshF85r+YWDNCQ2apd9PNs/zL6ttKm0nD1IFwvxyg3YOTI7FHl4unrw==",
514 | "dev": true,
515 | "dependencies": {
516 | "espree": "^6.1.2",
517 | "esutils": "^2.0.2",
518 | "natural-compare": "^1.4.0",
519 | "requireindex": "~1.2.0"
520 | },
521 | "engines": {
522 | "node": ">=0.10.0"
523 | }
524 | },
525 | "node_modules/eslint-plugin-sort-keys-fix/node_modules/acorn": {
526 | "version": "7.4.1",
527 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
528 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
529 | "dev": true,
530 | "bin": {
531 | "acorn": "bin/acorn"
532 | },
533 | "engines": {
534 | "node": ">=0.4.0"
535 | }
536 | },
537 | "node_modules/eslint-plugin-sort-keys-fix/node_modules/eslint-visitor-keys": {
538 | "version": "1.3.0",
539 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
540 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
541 | "dev": true,
542 | "engines": {
543 | "node": ">=4"
544 | }
545 | },
546 | "node_modules/eslint-plugin-sort-keys-fix/node_modules/espree": {
547 | "version": "6.2.1",
548 | "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
549 | "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
550 | "dev": true,
551 | "dependencies": {
552 | "acorn": "^7.1.1",
553 | "acorn-jsx": "^5.2.0",
554 | "eslint-visitor-keys": "^1.1.0"
555 | },
556 | "engines": {
557 | "node": ">=6.0.0"
558 | }
559 | },
560 | "node_modules/eslint-plugin-sort-requires": {
561 | "version": "2.1.0",
562 | "resolved": "git+https://npm@github.com/Hypfer/eslint-plugin-sort-requires.git#3e216dd9e9589b87671a3e7bf4084a0bd96e920e",
563 | "dev": true,
564 | "license": "MIT"
565 | },
566 | "node_modules/eslint-scope": {
567 | "version": "7.2.2",
568 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
569 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
570 | "dev": true,
571 | "dependencies": {
572 | "esrecurse": "^4.3.0",
573 | "estraverse": "^5.2.0"
574 | },
575 | "engines": {
576 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
577 | },
578 | "funding": {
579 | "url": "https://opencollective.com/eslint"
580 | }
581 | },
582 | "node_modules/eslint-utils": {
583 | "version": "3.0.0",
584 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
585 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
586 | "dev": true,
587 | "dependencies": {
588 | "eslint-visitor-keys": "^2.0.0"
589 | },
590 | "engines": {
591 | "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
592 | },
593 | "funding": {
594 | "url": "https://github.com/sponsors/mysticatea"
595 | },
596 | "peerDependencies": {
597 | "eslint": ">=5"
598 | }
599 | },
600 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
601 | "version": "2.1.0",
602 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
603 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
604 | "dev": true,
605 | "engines": {
606 | "node": ">=10"
607 | }
608 | },
609 | "node_modules/eslint-visitor-keys": {
610 | "version": "3.4.2",
611 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz",
612 | "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==",
613 | "dev": true,
614 | "engines": {
615 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
616 | },
617 | "funding": {
618 | "url": "https://opencollective.com/eslint"
619 | }
620 | },
621 | "node_modules/espree": {
622 | "version": "9.6.1",
623 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
624 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
625 | "dev": true,
626 | "dependencies": {
627 | "acorn": "^8.9.0",
628 | "acorn-jsx": "^5.3.2",
629 | "eslint-visitor-keys": "^3.4.1"
630 | },
631 | "engines": {
632 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
633 | },
634 | "funding": {
635 | "url": "https://opencollective.com/eslint"
636 | }
637 | },
638 | "node_modules/esquery": {
639 | "version": "1.6.0",
640 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
641 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
642 | "dev": true,
643 | "dependencies": {
644 | "estraverse": "^5.1.0"
645 | },
646 | "engines": {
647 | "node": ">=0.10"
648 | }
649 | },
650 | "node_modules/esrecurse": {
651 | "version": "4.3.0",
652 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
653 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
654 | "dev": true,
655 | "dependencies": {
656 | "estraverse": "^5.2.0"
657 | },
658 | "engines": {
659 | "node": ">=4.0"
660 | }
661 | },
662 | "node_modules/estraverse": {
663 | "version": "5.3.0",
664 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
665 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
666 | "dev": true,
667 | "engines": {
668 | "node": ">=4.0"
669 | }
670 | },
671 | "node_modules/esutils": {
672 | "version": "2.0.3",
673 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
674 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
675 | "dev": true,
676 | "engines": {
677 | "node": ">=0.10.0"
678 | }
679 | },
680 | "node_modules/fast-deep-equal": {
681 | "version": "3.1.3",
682 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
683 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
684 | "dev": true
685 | },
686 | "node_modules/fast-json-stable-stringify": {
687 | "version": "2.1.0",
688 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
689 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
690 | "dev": true
691 | },
692 | "node_modules/fast-levenshtein": {
693 | "version": "2.0.6",
694 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
695 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
696 | "dev": true
697 | },
698 | "node_modules/file-entry-cache": {
699 | "version": "6.0.1",
700 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
701 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
702 | "dev": true,
703 | "dependencies": {
704 | "flat-cache": "^3.0.4"
705 | },
706 | "engines": {
707 | "node": "^10.12.0 || >=12.0.0"
708 | }
709 | },
710 | "node_modules/flat-cache": {
711 | "version": "3.0.4",
712 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
713 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
714 | "dev": true,
715 | "dependencies": {
716 | "flatted": "^3.1.0",
717 | "rimraf": "^3.0.2"
718 | },
719 | "engines": {
720 | "node": "^10.12.0 || >=12.0.0"
721 | }
722 | },
723 | "node_modules/flatted": {
724 | "version": "3.2.7",
725 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
726 | "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
727 | "dev": true
728 | },
729 | "node_modules/fs.realpath": {
730 | "version": "1.0.0",
731 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
732 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
733 | },
734 | "node_modules/functional-red-black-tree": {
735 | "version": "1.0.1",
736 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
737 | "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
738 | "dev": true
739 | },
740 | "node_modules/glob": {
741 | "version": "7.2.3",
742 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
743 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
744 | "dependencies": {
745 | "fs.realpath": "^1.0.0",
746 | "inflight": "^1.0.4",
747 | "inherits": "2",
748 | "minimatch": "^3.1.1",
749 | "once": "^1.3.0",
750 | "path-is-absolute": "^1.0.0"
751 | },
752 | "engines": {
753 | "node": "*"
754 | },
755 | "funding": {
756 | "url": "https://github.com/sponsors/isaacs"
757 | }
758 | },
759 | "node_modules/glob-parent": {
760 | "version": "6.0.2",
761 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
762 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
763 | "dev": true,
764 | "dependencies": {
765 | "is-glob": "^4.0.3"
766 | },
767 | "engines": {
768 | "node": ">=10.13.0"
769 | }
770 | },
771 | "node_modules/globals": {
772 | "version": "13.20.0",
773 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
774 | "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
775 | "dev": true,
776 | "dependencies": {
777 | "type-fest": "^0.20.2"
778 | },
779 | "engines": {
780 | "node": ">=8"
781 | },
782 | "funding": {
783 | "url": "https://github.com/sponsors/sindresorhus"
784 | }
785 | },
786 | "node_modules/grapheme-splitter": {
787 | "version": "1.0.4",
788 | "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
789 | "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
790 | "dev": true
791 | },
792 | "node_modules/has-flag": {
793 | "version": "4.0.0",
794 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
795 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
796 | "dev": true,
797 | "engines": {
798 | "node": ">=8"
799 | }
800 | },
801 | "node_modules/help-me": {
802 | "version": "3.0.0",
803 | "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz",
804 | "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
805 | "dependencies": {
806 | "glob": "^7.1.6",
807 | "readable-stream": "^3.6.0"
808 | }
809 | },
810 | "node_modules/ieee754": {
811 | "version": "1.2.1",
812 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
813 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
814 | "funding": [
815 | {
816 | "type": "github",
817 | "url": "https://github.com/sponsors/feross"
818 | },
819 | {
820 | "type": "patreon",
821 | "url": "https://www.patreon.com/feross"
822 | },
823 | {
824 | "type": "consulting",
825 | "url": "https://feross.org/support"
826 | }
827 | ]
828 | },
829 | "node_modules/ignore": {
830 | "version": "5.2.4",
831 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
832 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
833 | "dev": true,
834 | "engines": {
835 | "node": ">= 4"
836 | }
837 | },
838 | "node_modules/import-fresh": {
839 | "version": "3.3.0",
840 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
841 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
842 | "dev": true,
843 | "dependencies": {
844 | "parent-module": "^1.0.0",
845 | "resolve-from": "^4.0.0"
846 | },
847 | "engines": {
848 | "node": ">=6"
849 | },
850 | "funding": {
851 | "url": "https://github.com/sponsors/sindresorhus"
852 | }
853 | },
854 | "node_modules/imurmurhash": {
855 | "version": "0.1.4",
856 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
857 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
858 | "dev": true,
859 | "engines": {
860 | "node": ">=0.8.19"
861 | }
862 | },
863 | "node_modules/inflight": {
864 | "version": "1.0.6",
865 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
866 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
867 | "dependencies": {
868 | "once": "^1.3.0",
869 | "wrappy": "1"
870 | }
871 | },
872 | "node_modules/inherits": {
873 | "version": "2.0.4",
874 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
875 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
876 | },
877 | "node_modules/is-extglob": {
878 | "version": "2.1.1",
879 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
880 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
881 | "dev": true,
882 | "engines": {
883 | "node": ">=0.10.0"
884 | }
885 | },
886 | "node_modules/is-glob": {
887 | "version": "4.0.3",
888 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
889 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
890 | "dev": true,
891 | "dependencies": {
892 | "is-extglob": "^2.1.1"
893 | },
894 | "engines": {
895 | "node": ">=0.10.0"
896 | }
897 | },
898 | "node_modules/isexe": {
899 | "version": "2.0.0",
900 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
901 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
902 | "dev": true
903 | },
904 | "node_modules/js-sdsl": {
905 | "version": "4.3.0",
906 | "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
907 | "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
908 | "funding": {
909 | "type": "opencollective",
910 | "url": "https://opencollective.com/js-sdsl"
911 | }
912 | },
913 | "node_modules/js-yaml": {
914 | "version": "4.1.0",
915 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
916 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
917 | "dev": true,
918 | "dependencies": {
919 | "argparse": "^2.0.1"
920 | },
921 | "bin": {
922 | "js-yaml": "bin/js-yaml.js"
923 | }
924 | },
925 | "node_modules/jsdoc-type-pratt-parser": {
926 | "version": "4.0.0",
927 | "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
928 | "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
929 | "dev": true,
930 | "engines": {
931 | "node": ">=12.0.0"
932 | }
933 | },
934 | "node_modules/jsdoctypeparser": {
935 | "version": "9.0.0",
936 | "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz",
937 | "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==",
938 | "dev": true,
939 | "bin": {
940 | "jsdoctypeparser": "bin/jsdoctypeparser"
941 | },
942 | "engines": {
943 | "node": ">=10"
944 | }
945 | },
946 | "node_modules/json-schema-traverse": {
947 | "version": "0.4.1",
948 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
949 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
950 | "dev": true
951 | },
952 | "node_modules/json-stable-stringify-without-jsonify": {
953 | "version": "1.0.1",
954 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
955 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
956 | "dev": true
957 | },
958 | "node_modules/leven": {
959 | "version": "2.1.0",
960 | "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
961 | "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
962 | "engines": {
963 | "node": ">=0.10.0"
964 | }
965 | },
966 | "node_modules/levn": {
967 | "version": "0.4.1",
968 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
969 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
970 | "dev": true,
971 | "dependencies": {
972 | "prelude-ls": "^1.2.1",
973 | "type-check": "~0.4.0"
974 | },
975 | "engines": {
976 | "node": ">= 0.8.0"
977 | }
978 | },
979 | "node_modules/lodash.merge": {
980 | "version": "4.6.2",
981 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
982 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
983 | "dev": true
984 | },
985 | "node_modules/lru-cache": {
986 | "version": "6.0.0",
987 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
988 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
989 | "dependencies": {
990 | "yallist": "^4.0.0"
991 | },
992 | "engines": {
993 | "node": ">=10"
994 | }
995 | },
996 | "node_modules/minimatch": {
997 | "version": "3.1.2",
998 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
999 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1000 | "dependencies": {
1001 | "brace-expansion": "^1.1.7"
1002 | },
1003 | "engines": {
1004 | "node": "*"
1005 | }
1006 | },
1007 | "node_modules/minimist": {
1008 | "version": "1.2.8",
1009 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
1010 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
1011 | "funding": {
1012 | "url": "https://github.com/sponsors/ljharb"
1013 | }
1014 | },
1015 | "node_modules/mqtt": {
1016 | "version": "4.3.7",
1017 | "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz",
1018 | "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==",
1019 | "dependencies": {
1020 | "commist": "^1.0.0",
1021 | "concat-stream": "^2.0.0",
1022 | "debug": "^4.1.1",
1023 | "duplexify": "^4.1.1",
1024 | "help-me": "^3.0.0",
1025 | "inherits": "^2.0.3",
1026 | "lru-cache": "^6.0.0",
1027 | "minimist": "^1.2.5",
1028 | "mqtt-packet": "^6.8.0",
1029 | "number-allocator": "^1.0.9",
1030 | "pump": "^3.0.0",
1031 | "readable-stream": "^3.6.0",
1032 | "reinterval": "^1.1.0",
1033 | "rfdc": "^1.3.0",
1034 | "split2": "^3.1.0",
1035 | "ws": "^7.5.5",
1036 | "xtend": "^4.0.2"
1037 | },
1038 | "bin": {
1039 | "mqtt": "bin/mqtt.js",
1040 | "mqtt_pub": "bin/pub.js",
1041 | "mqtt_sub": "bin/sub.js"
1042 | },
1043 | "engines": {
1044 | "node": ">=10.0.0"
1045 | }
1046 | },
1047 | "node_modules/mqtt-packet": {
1048 | "version": "6.10.0",
1049 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
1050 | "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
1051 | "dependencies": {
1052 | "bl": "^4.0.2",
1053 | "debug": "^4.1.1",
1054 | "process-nextick-args": "^2.0.1"
1055 | }
1056 | },
1057 | "node_modules/ms": {
1058 | "version": "2.1.3",
1059 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1060 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1061 | },
1062 | "node_modules/natural-compare": {
1063 | "version": "1.4.0",
1064 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
1065 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
1066 | "dev": true
1067 | },
1068 | "node_modules/number-allocator": {
1069 | "version": "1.0.14",
1070 | "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz",
1071 | "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
1072 | "dependencies": {
1073 | "debug": "^4.3.1",
1074 | "js-sdsl": "4.3.0"
1075 | }
1076 | },
1077 | "node_modules/once": {
1078 | "version": "1.4.0",
1079 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1080 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1081 | "dependencies": {
1082 | "wrappy": "1"
1083 | }
1084 | },
1085 | "node_modules/optionator": {
1086 | "version": "0.9.3",
1087 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
1088 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
1089 | "dev": true,
1090 | "dependencies": {
1091 | "@aashutoshrathi/word-wrap": "^1.2.3",
1092 | "deep-is": "^0.1.3",
1093 | "fast-levenshtein": "^2.0.6",
1094 | "levn": "^0.4.1",
1095 | "prelude-ls": "^1.2.1",
1096 | "type-check": "^0.4.0"
1097 | },
1098 | "engines": {
1099 | "node": ">= 0.8.0"
1100 | }
1101 | },
1102 | "node_modules/parent-module": {
1103 | "version": "1.0.1",
1104 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
1105 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
1106 | "dev": true,
1107 | "dependencies": {
1108 | "callsites": "^3.0.0"
1109 | },
1110 | "engines": {
1111 | "node": ">=6"
1112 | }
1113 | },
1114 | "node_modules/parse-imports": {
1115 | "version": "2.1.1",
1116 | "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz",
1117 | "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==",
1118 | "dev": true,
1119 | "dependencies": {
1120 | "es-module-lexer": "^1.5.3",
1121 | "slashes": "^3.0.12"
1122 | },
1123 | "engines": {
1124 | "node": ">= 18"
1125 | }
1126 | },
1127 | "node_modules/path-is-absolute": {
1128 | "version": "1.0.1",
1129 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1130 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1131 | "engines": {
1132 | "node": ">=0.10.0"
1133 | }
1134 | },
1135 | "node_modules/path-key": {
1136 | "version": "3.1.1",
1137 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1138 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1139 | "dev": true,
1140 | "engines": {
1141 | "node": ">=8"
1142 | }
1143 | },
1144 | "node_modules/prelude-ls": {
1145 | "version": "1.2.1",
1146 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
1147 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
1148 | "dev": true,
1149 | "engines": {
1150 | "node": ">= 0.8.0"
1151 | }
1152 | },
1153 | "node_modules/process-nextick-args": {
1154 | "version": "2.0.1",
1155 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1156 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
1157 | },
1158 | "node_modules/pump": {
1159 | "version": "3.0.0",
1160 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
1161 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
1162 | "dependencies": {
1163 | "end-of-stream": "^1.1.0",
1164 | "once": "^1.3.1"
1165 | }
1166 | },
1167 | "node_modules/punycode": {
1168 | "version": "2.3.0",
1169 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
1170 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
1171 | "dev": true,
1172 | "engines": {
1173 | "node": ">=6"
1174 | }
1175 | },
1176 | "node_modules/readable-stream": {
1177 | "version": "3.6.2",
1178 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
1179 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
1180 | "dependencies": {
1181 | "inherits": "^2.0.3",
1182 | "string_decoder": "^1.1.1",
1183 | "util-deprecate": "^1.0.1"
1184 | },
1185 | "engines": {
1186 | "node": ">= 6"
1187 | }
1188 | },
1189 | "node_modules/refa": {
1190 | "version": "0.9.1",
1191 | "resolved": "https://registry.npmjs.org/refa/-/refa-0.9.1.tgz",
1192 | "integrity": "sha512-egU8LgFq2VXlAfUi8Jcbr5X38wEOadMFf8tCbshgcpVCYlE7k84pJOSlnvXF+muDB4igkdVMq7Z/kiNPqDT9TA==",
1193 | "dev": true,
1194 | "dependencies": {
1195 | "regexpp": "^3.2.0"
1196 | }
1197 | },
1198 | "node_modules/regexp-ast-analysis": {
1199 | "version": "0.5.1",
1200 | "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.5.1.tgz",
1201 | "integrity": "sha512-Ca/g9gaTNuMewLuu+mBIq4vCrGRSO8AE9bP32NMQjJ/wBTdWq0g96qLkBb0NbGwEbp7S/q+NQF3o7veeuRfg0g==",
1202 | "dev": true,
1203 | "dependencies": {
1204 | "refa": "^0.9.0",
1205 | "regexpp": "^3.2.0"
1206 | }
1207 | },
1208 | "node_modules/regexpp": {
1209 | "version": "3.2.0",
1210 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
1211 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
1212 | "dev": true,
1213 | "engines": {
1214 | "node": ">=8"
1215 | },
1216 | "funding": {
1217 | "url": "https://github.com/sponsors/mysticatea"
1218 | }
1219 | },
1220 | "node_modules/reinterval": {
1221 | "version": "1.1.0",
1222 | "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
1223 | "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
1224 | },
1225 | "node_modules/requireindex": {
1226 | "version": "1.2.0",
1227 | "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
1228 | "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
1229 | "dev": true,
1230 | "engines": {
1231 | "node": ">=0.10.5"
1232 | }
1233 | },
1234 | "node_modules/resolve-from": {
1235 | "version": "4.0.0",
1236 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
1237 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
1238 | "dev": true,
1239 | "engines": {
1240 | "node": ">=4"
1241 | }
1242 | },
1243 | "node_modules/rfdc": {
1244 | "version": "1.3.0",
1245 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
1246 | "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
1247 | },
1248 | "node_modules/rimraf": {
1249 | "version": "3.0.2",
1250 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1251 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1252 | "dev": true,
1253 | "dependencies": {
1254 | "glob": "^7.1.3"
1255 | },
1256 | "bin": {
1257 | "rimraf": "bin.js"
1258 | },
1259 | "funding": {
1260 | "url": "https://github.com/sponsors/isaacs"
1261 | }
1262 | },
1263 | "node_modules/safe-buffer": {
1264 | "version": "5.2.1",
1265 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1266 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1267 | "funding": [
1268 | {
1269 | "type": "github",
1270 | "url": "https://github.com/sponsors/feross"
1271 | },
1272 | {
1273 | "type": "patreon",
1274 | "url": "https://www.patreon.com/feross"
1275 | },
1276 | {
1277 | "type": "consulting",
1278 | "url": "https://feross.org/support"
1279 | }
1280 | ]
1281 | },
1282 | "node_modules/scslre": {
1283 | "version": "0.1.6",
1284 | "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.1.6.tgz",
1285 | "integrity": "sha512-JORxVRlQTfjvlOAaiQKebgFElyAm5/W8b50lgaZ0OkEnKnagJW2ufDh3xRfU75UD9z3FGIu1gL1IyR3Poa6Qmw==",
1286 | "dev": true,
1287 | "dependencies": {
1288 | "refa": "^0.9.0",
1289 | "regexp-ast-analysis": "^0.2.3",
1290 | "regexpp": "^3.2.0"
1291 | }
1292 | },
1293 | "node_modules/scslre/node_modules/regexp-ast-analysis": {
1294 | "version": "0.2.4",
1295 | "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.2.4.tgz",
1296 | "integrity": "sha512-8L7kOZQaKPxKKAwGuUZxTQtlO3WZ+tiXy4s6G6PKL6trbOXcZoumwC3AOHHFtI/xoSbNxt7jgLvCnP1UADLWqg==",
1297 | "dev": true,
1298 | "dependencies": {
1299 | "refa": "^0.9.0",
1300 | "regexpp": "^3.2.0"
1301 | }
1302 | },
1303 | "node_modules/semver": {
1304 | "version": "7.6.3",
1305 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
1306 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
1307 | "dev": true,
1308 | "bin": {
1309 | "semver": "bin/semver.js"
1310 | },
1311 | "engines": {
1312 | "node": ">=10"
1313 | }
1314 | },
1315 | "node_modules/shebang-command": {
1316 | "version": "2.0.0",
1317 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1318 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1319 | "dev": true,
1320 | "dependencies": {
1321 | "shebang-regex": "^3.0.0"
1322 | },
1323 | "engines": {
1324 | "node": ">=8"
1325 | }
1326 | },
1327 | "node_modules/shebang-regex": {
1328 | "version": "3.0.0",
1329 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1330 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1331 | "dev": true,
1332 | "engines": {
1333 | "node": ">=8"
1334 | }
1335 | },
1336 | "node_modules/slashes": {
1337 | "version": "3.0.12",
1338 | "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz",
1339 | "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==",
1340 | "dev": true
1341 | },
1342 | "node_modules/spdx-exceptions": {
1343 | "version": "2.5.0",
1344 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
1345 | "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
1346 | "dev": true
1347 | },
1348 | "node_modules/spdx-expression-parse": {
1349 | "version": "4.0.0",
1350 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz",
1351 | "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==",
1352 | "dev": true,
1353 | "dependencies": {
1354 | "spdx-exceptions": "^2.1.0",
1355 | "spdx-license-ids": "^3.0.0"
1356 | }
1357 | },
1358 | "node_modules/spdx-license-ids": {
1359 | "version": "3.0.20",
1360 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
1361 | "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
1362 | "dev": true
1363 | },
1364 | "node_modules/split2": {
1365 | "version": "3.2.2",
1366 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
1367 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
1368 | "dependencies": {
1369 | "readable-stream": "^3.0.0"
1370 | }
1371 | },
1372 | "node_modules/stream-shift": {
1373 | "version": "1.0.1",
1374 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
1375 | "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
1376 | },
1377 | "node_modules/string_decoder": {
1378 | "version": "1.3.0",
1379 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1380 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1381 | "dependencies": {
1382 | "safe-buffer": "~5.2.0"
1383 | }
1384 | },
1385 | "node_modules/strip-ansi": {
1386 | "version": "6.0.1",
1387 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1388 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1389 | "dev": true,
1390 | "dependencies": {
1391 | "ansi-regex": "^5.0.1"
1392 | },
1393 | "engines": {
1394 | "node": ">=8"
1395 | }
1396 | },
1397 | "node_modules/strip-json-comments": {
1398 | "version": "3.1.1",
1399 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
1400 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
1401 | "dev": true,
1402 | "engines": {
1403 | "node": ">=8"
1404 | },
1405 | "funding": {
1406 | "url": "https://github.com/sponsors/sindresorhus"
1407 | }
1408 | },
1409 | "node_modules/supports-color": {
1410 | "version": "7.2.0",
1411 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1412 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1413 | "dev": true,
1414 | "dependencies": {
1415 | "has-flag": "^4.0.0"
1416 | },
1417 | "engines": {
1418 | "node": ">=8"
1419 | }
1420 | },
1421 | "node_modules/synckit": {
1422 | "version": "0.9.1",
1423 | "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
1424 | "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
1425 | "dev": true,
1426 | "dependencies": {
1427 | "@pkgr/core": "^0.1.0",
1428 | "tslib": "^2.6.2"
1429 | },
1430 | "engines": {
1431 | "node": "^14.18.0 || >=16.0.0"
1432 | },
1433 | "funding": {
1434 | "url": "https://opencollective.com/unts"
1435 | }
1436 | },
1437 | "node_modules/text-table": {
1438 | "version": "0.2.0",
1439 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
1440 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
1441 | "dev": true
1442 | },
1443 | "node_modules/tslib": {
1444 | "version": "2.7.0",
1445 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
1446 | "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
1447 | "dev": true
1448 | },
1449 | "node_modules/type-check": {
1450 | "version": "0.4.0",
1451 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
1452 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
1453 | "dev": true,
1454 | "dependencies": {
1455 | "prelude-ls": "^1.2.1"
1456 | },
1457 | "engines": {
1458 | "node": ">= 0.8.0"
1459 | }
1460 | },
1461 | "node_modules/type-fest": {
1462 | "version": "0.20.2",
1463 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
1464 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
1465 | "dev": true,
1466 | "engines": {
1467 | "node": ">=10"
1468 | },
1469 | "funding": {
1470 | "url": "https://github.com/sponsors/sindresorhus"
1471 | }
1472 | },
1473 | "node_modules/typedarray": {
1474 | "version": "0.0.6",
1475 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
1476 | "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
1477 | },
1478 | "node_modules/uri-js": {
1479 | "version": "4.4.1",
1480 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1481 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1482 | "dev": true,
1483 | "dependencies": {
1484 | "punycode": "^2.1.0"
1485 | }
1486 | },
1487 | "node_modules/util-deprecate": {
1488 | "version": "1.0.2",
1489 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1490 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
1491 | },
1492 | "node_modules/v8-compile-cache": {
1493 | "version": "2.3.0",
1494 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
1495 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
1496 | "dev": true
1497 | },
1498 | "node_modules/which": {
1499 | "version": "2.0.2",
1500 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1501 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1502 | "dev": true,
1503 | "dependencies": {
1504 | "isexe": "^2.0.0"
1505 | },
1506 | "bin": {
1507 | "node-which": "bin/node-which"
1508 | },
1509 | "engines": {
1510 | "node": ">= 8"
1511 | }
1512 | },
1513 | "node_modules/wrappy": {
1514 | "version": "1.0.2",
1515 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1516 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
1517 | },
1518 | "node_modules/ws": {
1519 | "version": "7.5.10",
1520 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
1521 | "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
1522 | "engines": {
1523 | "node": ">=8.3.0"
1524 | },
1525 | "peerDependencies": {
1526 | "bufferutil": "^4.0.1",
1527 | "utf-8-validate": "^5.0.2"
1528 | },
1529 | "peerDependenciesMeta": {
1530 | "bufferutil": {
1531 | "optional": true
1532 | },
1533 | "utf-8-validate": {
1534 | "optional": true
1535 | }
1536 | }
1537 | },
1538 | "node_modules/xtend": {
1539 | "version": "4.0.2",
1540 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1541 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
1542 | "engines": {
1543 | "node": ">=0.4"
1544 | }
1545 | },
1546 | "node_modules/yallist": {
1547 | "version": "4.0.0",
1548 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1549 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
1550 | }
1551 | },
1552 | "dependencies": {
1553 | "@aashutoshrathi/word-wrap": {
1554 | "version": "1.2.6",
1555 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
1556 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
1557 | "dev": true
1558 | },
1559 | "@es-joy/jsdoccomment": {
1560 | "version": "0.46.0",
1561 | "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz",
1562 | "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==",
1563 | "dev": true,
1564 | "requires": {
1565 | "comment-parser": "1.4.1",
1566 | "esquery": "^1.6.0",
1567 | "jsdoc-type-pratt-parser": "~4.0.0"
1568 | }
1569 | },
1570 | "@eslint/eslintrc": {
1571 | "version": "1.4.1",
1572 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
1573 | "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
1574 | "dev": true,
1575 | "requires": {
1576 | "ajv": "^6.12.4",
1577 | "debug": "^4.3.2",
1578 | "espree": "^9.4.0",
1579 | "globals": "^13.19.0",
1580 | "ignore": "^5.2.0",
1581 | "import-fresh": "^3.2.1",
1582 | "js-yaml": "^4.1.0",
1583 | "minimatch": "^3.1.2",
1584 | "strip-json-comments": "^3.1.1"
1585 | }
1586 | },
1587 | "@humanwhocodes/config-array": {
1588 | "version": "0.9.5",
1589 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
1590 | "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
1591 | "dev": true,
1592 | "requires": {
1593 | "@humanwhocodes/object-schema": "^1.2.1",
1594 | "debug": "^4.1.1",
1595 | "minimatch": "^3.0.4"
1596 | }
1597 | },
1598 | "@humanwhocodes/object-schema": {
1599 | "version": "1.2.1",
1600 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
1601 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
1602 | "dev": true
1603 | },
1604 | "@pkgr/core": {
1605 | "version": "0.1.1",
1606 | "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
1607 | "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
1608 | "dev": true
1609 | },
1610 | "acorn": {
1611 | "version": "8.12.1",
1612 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
1613 | "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
1614 | "dev": true
1615 | },
1616 | "acorn-jsx": {
1617 | "version": "5.3.2",
1618 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
1619 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
1620 | "dev": true,
1621 | "requires": {}
1622 | },
1623 | "ajv": {
1624 | "version": "6.12.6",
1625 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1626 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1627 | "dev": true,
1628 | "requires": {
1629 | "fast-deep-equal": "^3.1.1",
1630 | "fast-json-stable-stringify": "^2.0.0",
1631 | "json-schema-traverse": "^0.4.1",
1632 | "uri-js": "^4.2.2"
1633 | }
1634 | },
1635 | "ansi-regex": {
1636 | "version": "5.0.1",
1637 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1638 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1639 | "dev": true
1640 | },
1641 | "ansi-styles": {
1642 | "version": "4.3.0",
1643 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1644 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1645 | "dev": true,
1646 | "requires": {
1647 | "color-convert": "^2.0.1"
1648 | }
1649 | },
1650 | "are-docs-informative": {
1651 | "version": "0.0.2",
1652 | "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
1653 | "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
1654 | "dev": true
1655 | },
1656 | "argparse": {
1657 | "version": "2.0.1",
1658 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1659 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1660 | "dev": true
1661 | },
1662 | "balanced-match": {
1663 | "version": "1.0.2",
1664 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1665 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
1666 | },
1667 | "base64-js": {
1668 | "version": "1.5.1",
1669 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
1670 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
1671 | },
1672 | "bl": {
1673 | "version": "4.1.0",
1674 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
1675 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
1676 | "requires": {
1677 | "buffer": "^5.5.0",
1678 | "inherits": "^2.0.4",
1679 | "readable-stream": "^3.4.0"
1680 | }
1681 | },
1682 | "brace-expansion": {
1683 | "version": "1.1.11",
1684 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1685 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1686 | "requires": {
1687 | "balanced-match": "^1.0.0",
1688 | "concat-map": "0.0.1"
1689 | }
1690 | },
1691 | "buffer": {
1692 | "version": "5.7.1",
1693 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
1694 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
1695 | "requires": {
1696 | "base64-js": "^1.3.1",
1697 | "ieee754": "^1.1.13"
1698 | }
1699 | },
1700 | "buffer-from": {
1701 | "version": "1.1.2",
1702 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1703 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
1704 | },
1705 | "callsites": {
1706 | "version": "3.1.0",
1707 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
1708 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
1709 | "dev": true
1710 | },
1711 | "chalk": {
1712 | "version": "4.1.2",
1713 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1714 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1715 | "dev": true,
1716 | "requires": {
1717 | "ansi-styles": "^4.1.0",
1718 | "supports-color": "^7.1.0"
1719 | }
1720 | },
1721 | "color-convert": {
1722 | "version": "2.0.1",
1723 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1724 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1725 | "dev": true,
1726 | "requires": {
1727 | "color-name": "~1.1.4"
1728 | }
1729 | },
1730 | "color-name": {
1731 | "version": "1.1.4",
1732 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1733 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1734 | "dev": true
1735 | },
1736 | "comment-parser": {
1737 | "version": "1.4.1",
1738 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
1739 | "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
1740 | "dev": true
1741 | },
1742 | "commist": {
1743 | "version": "1.1.0",
1744 | "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
1745 | "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
1746 | "requires": {
1747 | "leven": "^2.1.0",
1748 | "minimist": "^1.1.0"
1749 | }
1750 | },
1751 | "concat-map": {
1752 | "version": "0.0.1",
1753 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1754 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
1755 | },
1756 | "concat-stream": {
1757 | "version": "2.0.0",
1758 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
1759 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
1760 | "requires": {
1761 | "buffer-from": "^1.0.0",
1762 | "inherits": "^2.0.3",
1763 | "readable-stream": "^3.0.2",
1764 | "typedarray": "^0.0.6"
1765 | }
1766 | },
1767 | "cross-spawn": {
1768 | "version": "7.0.3",
1769 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
1770 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
1771 | "dev": true,
1772 | "requires": {
1773 | "path-key": "^3.1.0",
1774 | "shebang-command": "^2.0.0",
1775 | "which": "^2.0.1"
1776 | }
1777 | },
1778 | "debug": {
1779 | "version": "4.3.7",
1780 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
1781 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
1782 | "requires": {
1783 | "ms": "^2.1.3"
1784 | }
1785 | },
1786 | "deep-is": {
1787 | "version": "0.1.4",
1788 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
1789 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
1790 | "dev": true
1791 | },
1792 | "doctrine": {
1793 | "version": "3.0.0",
1794 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
1795 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
1796 | "dev": true,
1797 | "requires": {
1798 | "esutils": "^2.0.2"
1799 | }
1800 | },
1801 | "duplexify": {
1802 | "version": "4.1.2",
1803 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz",
1804 | "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
1805 | "requires": {
1806 | "end-of-stream": "^1.4.1",
1807 | "inherits": "^2.0.3",
1808 | "readable-stream": "^3.1.1",
1809 | "stream-shift": "^1.0.0"
1810 | }
1811 | },
1812 | "end-of-stream": {
1813 | "version": "1.4.4",
1814 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
1815 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
1816 | "requires": {
1817 | "once": "^1.4.0"
1818 | }
1819 | },
1820 | "es-module-lexer": {
1821 | "version": "1.5.4",
1822 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
1823 | "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
1824 | "dev": true
1825 | },
1826 | "escape-string-regexp": {
1827 | "version": "4.0.0",
1828 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1829 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1830 | "dev": true
1831 | },
1832 | "eslint": {
1833 | "version": "8.16.0",
1834 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz",
1835 | "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==",
1836 | "dev": true,
1837 | "requires": {
1838 | "@eslint/eslintrc": "^1.3.0",
1839 | "@humanwhocodes/config-array": "^0.9.2",
1840 | "ajv": "^6.10.0",
1841 | "chalk": "^4.0.0",
1842 | "cross-spawn": "^7.0.2",
1843 | "debug": "^4.3.2",
1844 | "doctrine": "^3.0.0",
1845 | "escape-string-regexp": "^4.0.0",
1846 | "eslint-scope": "^7.1.1",
1847 | "eslint-utils": "^3.0.0",
1848 | "eslint-visitor-keys": "^3.3.0",
1849 | "espree": "^9.3.2",
1850 | "esquery": "^1.4.0",
1851 | "esutils": "^2.0.2",
1852 | "fast-deep-equal": "^3.1.3",
1853 | "file-entry-cache": "^6.0.1",
1854 | "functional-red-black-tree": "^1.0.1",
1855 | "glob-parent": "^6.0.1",
1856 | "globals": "^13.15.0",
1857 | "ignore": "^5.2.0",
1858 | "import-fresh": "^3.0.0",
1859 | "imurmurhash": "^0.1.4",
1860 | "is-glob": "^4.0.0",
1861 | "js-yaml": "^4.1.0",
1862 | "json-stable-stringify-without-jsonify": "^1.0.1",
1863 | "levn": "^0.4.1",
1864 | "lodash.merge": "^4.6.2",
1865 | "minimatch": "^3.1.2",
1866 | "natural-compare": "^1.4.0",
1867 | "optionator": "^0.9.1",
1868 | "regexpp": "^3.2.0",
1869 | "strip-ansi": "^6.0.1",
1870 | "strip-json-comments": "^3.1.0",
1871 | "text-table": "^0.2.0",
1872 | "v8-compile-cache": "^2.0.3"
1873 | }
1874 | },
1875 | "eslint-plugin-jsdoc": {
1876 | "version": "48.9.3",
1877 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.9.3.tgz",
1878 | "integrity": "sha512-9RUsTlW6ZlMgy+dd9uDreU9lZAh4Hxw2ZAV5T0hPtrWgbw0OnvuT3elF6ihnpAY+NCrJx8BUUmcBnKftc/F0qw==",
1879 | "dev": true,
1880 | "requires": {
1881 | "@es-joy/jsdoccomment": "~0.46.0",
1882 | "are-docs-informative": "^0.0.2",
1883 | "comment-parser": "1.4.1",
1884 | "debug": "^4.3.5",
1885 | "escape-string-regexp": "^4.0.0",
1886 | "esquery": "^1.6.0",
1887 | "parse-imports": "^2.1.1",
1888 | "semver": "^7.6.3",
1889 | "spdx-expression-parse": "^4.0.0",
1890 | "synckit": "^0.9.1"
1891 | }
1892 | },
1893 | "eslint-plugin-regexp": {
1894 | "version": "1.7.0",
1895 | "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.7.0.tgz",
1896 | "integrity": "sha512-nmhXqrEP+O+dz2z5MSkc41u/4fA8oakweoCUdfYwox7DBhzadEqZz8T+s6/UiY0NIU0kv+3UrzBfhPp4wUxbaA==",
1897 | "dev": true,
1898 | "requires": {
1899 | "comment-parser": "^1.1.2",
1900 | "eslint-utils": "^3.0.0",
1901 | "grapheme-splitter": "^1.0.4",
1902 | "jsdoctypeparser": "^9.0.0",
1903 | "refa": "^0.9.0",
1904 | "regexp-ast-analysis": "^0.5.1",
1905 | "regexpp": "^3.2.0",
1906 | "scslre": "^0.1.6"
1907 | }
1908 | },
1909 | "eslint-plugin-sort-keys-fix": {
1910 | "version": "1.1.2",
1911 | "resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.2.tgz",
1912 | "integrity": "sha512-DNPHFGCA0/hZIsfODbeLZqaGY/+q3vgtshF85r+YWDNCQ2apd9PNs/zL6ttKm0nD1IFwvxyg3YOTI7FHl4unrw==",
1913 | "dev": true,
1914 | "requires": {
1915 | "espree": "^6.1.2",
1916 | "esutils": "^2.0.2",
1917 | "natural-compare": "^1.4.0",
1918 | "requireindex": "~1.2.0"
1919 | },
1920 | "dependencies": {
1921 | "acorn": {
1922 | "version": "7.4.1",
1923 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
1924 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
1925 | "dev": true
1926 | },
1927 | "eslint-visitor-keys": {
1928 | "version": "1.3.0",
1929 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
1930 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
1931 | "dev": true
1932 | },
1933 | "espree": {
1934 | "version": "6.2.1",
1935 | "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
1936 | "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
1937 | "dev": true,
1938 | "requires": {
1939 | "acorn": "^7.1.1",
1940 | "acorn-jsx": "^5.2.0",
1941 | "eslint-visitor-keys": "^1.1.0"
1942 | }
1943 | }
1944 | }
1945 | },
1946 | "eslint-plugin-sort-requires": {
1947 | "version": "git+https://npm@github.com/Hypfer/eslint-plugin-sort-requires.git#3e216dd9e9589b87671a3e7bf4084a0bd96e920e",
1948 | "dev": true,
1949 | "from": "eslint-plugin-sort-requires@git+https://npm@github.com/Hypfer/eslint-plugin-sort-requires.git#2.1.1"
1950 | },
1951 | "eslint-scope": {
1952 | "version": "7.2.2",
1953 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
1954 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
1955 | "dev": true,
1956 | "requires": {
1957 | "esrecurse": "^4.3.0",
1958 | "estraverse": "^5.2.0"
1959 | }
1960 | },
1961 | "eslint-utils": {
1962 | "version": "3.0.0",
1963 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
1964 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
1965 | "dev": true,
1966 | "requires": {
1967 | "eslint-visitor-keys": "^2.0.0"
1968 | },
1969 | "dependencies": {
1970 | "eslint-visitor-keys": {
1971 | "version": "2.1.0",
1972 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
1973 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
1974 | "dev": true
1975 | }
1976 | }
1977 | },
1978 | "eslint-visitor-keys": {
1979 | "version": "3.4.2",
1980 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz",
1981 | "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==",
1982 | "dev": true
1983 | },
1984 | "espree": {
1985 | "version": "9.6.1",
1986 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
1987 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
1988 | "dev": true,
1989 | "requires": {
1990 | "acorn": "^8.9.0",
1991 | "acorn-jsx": "^5.3.2",
1992 | "eslint-visitor-keys": "^3.4.1"
1993 | }
1994 | },
1995 | "esquery": {
1996 | "version": "1.6.0",
1997 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
1998 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
1999 | "dev": true,
2000 | "requires": {
2001 | "estraverse": "^5.1.0"
2002 | }
2003 | },
2004 | "esrecurse": {
2005 | "version": "4.3.0",
2006 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
2007 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
2008 | "dev": true,
2009 | "requires": {
2010 | "estraverse": "^5.2.0"
2011 | }
2012 | },
2013 | "estraverse": {
2014 | "version": "5.3.0",
2015 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
2016 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
2017 | "dev": true
2018 | },
2019 | "esutils": {
2020 | "version": "2.0.3",
2021 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
2022 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
2023 | "dev": true
2024 | },
2025 | "fast-deep-equal": {
2026 | "version": "3.1.3",
2027 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
2028 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
2029 | "dev": true
2030 | },
2031 | "fast-json-stable-stringify": {
2032 | "version": "2.1.0",
2033 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
2034 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
2035 | "dev": true
2036 | },
2037 | "fast-levenshtein": {
2038 | "version": "2.0.6",
2039 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
2040 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
2041 | "dev": true
2042 | },
2043 | "file-entry-cache": {
2044 | "version": "6.0.1",
2045 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
2046 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
2047 | "dev": true,
2048 | "requires": {
2049 | "flat-cache": "^3.0.4"
2050 | }
2051 | },
2052 | "flat-cache": {
2053 | "version": "3.0.4",
2054 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
2055 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
2056 | "dev": true,
2057 | "requires": {
2058 | "flatted": "^3.1.0",
2059 | "rimraf": "^3.0.2"
2060 | }
2061 | },
2062 | "flatted": {
2063 | "version": "3.2.7",
2064 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
2065 | "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
2066 | "dev": true
2067 | },
2068 | "fs.realpath": {
2069 | "version": "1.0.0",
2070 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
2071 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
2072 | },
2073 | "functional-red-black-tree": {
2074 | "version": "1.0.1",
2075 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
2076 | "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
2077 | "dev": true
2078 | },
2079 | "glob": {
2080 | "version": "7.2.3",
2081 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
2082 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
2083 | "requires": {
2084 | "fs.realpath": "^1.0.0",
2085 | "inflight": "^1.0.4",
2086 | "inherits": "2",
2087 | "minimatch": "^3.1.1",
2088 | "once": "^1.3.0",
2089 | "path-is-absolute": "^1.0.0"
2090 | }
2091 | },
2092 | "glob-parent": {
2093 | "version": "6.0.2",
2094 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
2095 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
2096 | "dev": true,
2097 | "requires": {
2098 | "is-glob": "^4.0.3"
2099 | }
2100 | },
2101 | "globals": {
2102 | "version": "13.20.0",
2103 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
2104 | "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
2105 | "dev": true,
2106 | "requires": {
2107 | "type-fest": "^0.20.2"
2108 | }
2109 | },
2110 | "grapheme-splitter": {
2111 | "version": "1.0.4",
2112 | "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
2113 | "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
2114 | "dev": true
2115 | },
2116 | "has-flag": {
2117 | "version": "4.0.0",
2118 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2119 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
2120 | "dev": true
2121 | },
2122 | "help-me": {
2123 | "version": "3.0.0",
2124 | "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz",
2125 | "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
2126 | "requires": {
2127 | "glob": "^7.1.6",
2128 | "readable-stream": "^3.6.0"
2129 | }
2130 | },
2131 | "ieee754": {
2132 | "version": "1.2.1",
2133 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
2134 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
2135 | },
2136 | "ignore": {
2137 | "version": "5.2.4",
2138 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
2139 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
2140 | "dev": true
2141 | },
2142 | "import-fresh": {
2143 | "version": "3.3.0",
2144 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
2145 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
2146 | "dev": true,
2147 | "requires": {
2148 | "parent-module": "^1.0.0",
2149 | "resolve-from": "^4.0.0"
2150 | }
2151 | },
2152 | "imurmurhash": {
2153 | "version": "0.1.4",
2154 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
2155 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
2156 | "dev": true
2157 | },
2158 | "inflight": {
2159 | "version": "1.0.6",
2160 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
2161 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
2162 | "requires": {
2163 | "once": "^1.3.0",
2164 | "wrappy": "1"
2165 | }
2166 | },
2167 | "inherits": {
2168 | "version": "2.0.4",
2169 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
2170 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
2171 | },
2172 | "is-extglob": {
2173 | "version": "2.1.1",
2174 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
2175 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
2176 | "dev": true
2177 | },
2178 | "is-glob": {
2179 | "version": "4.0.3",
2180 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
2181 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
2182 | "dev": true,
2183 | "requires": {
2184 | "is-extglob": "^2.1.1"
2185 | }
2186 | },
2187 | "isexe": {
2188 | "version": "2.0.0",
2189 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
2190 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
2191 | "dev": true
2192 | },
2193 | "js-sdsl": {
2194 | "version": "4.3.0",
2195 | "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
2196 | "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
2197 | },
2198 | "js-yaml": {
2199 | "version": "4.1.0",
2200 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
2201 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
2202 | "dev": true,
2203 | "requires": {
2204 | "argparse": "^2.0.1"
2205 | }
2206 | },
2207 | "jsdoc-type-pratt-parser": {
2208 | "version": "4.0.0",
2209 | "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
2210 | "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
2211 | "dev": true
2212 | },
2213 | "jsdoctypeparser": {
2214 | "version": "9.0.0",
2215 | "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz",
2216 | "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==",
2217 | "dev": true
2218 | },
2219 | "json-schema-traverse": {
2220 | "version": "0.4.1",
2221 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
2222 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
2223 | "dev": true
2224 | },
2225 | "json-stable-stringify-without-jsonify": {
2226 | "version": "1.0.1",
2227 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
2228 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
2229 | "dev": true
2230 | },
2231 | "leven": {
2232 | "version": "2.1.0",
2233 | "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
2234 | "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="
2235 | },
2236 | "levn": {
2237 | "version": "0.4.1",
2238 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
2239 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
2240 | "dev": true,
2241 | "requires": {
2242 | "prelude-ls": "^1.2.1",
2243 | "type-check": "~0.4.0"
2244 | }
2245 | },
2246 | "lodash.merge": {
2247 | "version": "4.6.2",
2248 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
2249 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
2250 | "dev": true
2251 | },
2252 | "lru-cache": {
2253 | "version": "6.0.0",
2254 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
2255 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
2256 | "requires": {
2257 | "yallist": "^4.0.0"
2258 | }
2259 | },
2260 | "minimatch": {
2261 | "version": "3.1.2",
2262 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
2263 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
2264 | "requires": {
2265 | "brace-expansion": "^1.1.7"
2266 | }
2267 | },
2268 | "minimist": {
2269 | "version": "1.2.8",
2270 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
2271 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
2272 | },
2273 | "mqtt": {
2274 | "version": "4.3.7",
2275 | "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz",
2276 | "integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==",
2277 | "requires": {
2278 | "commist": "^1.0.0",
2279 | "concat-stream": "^2.0.0",
2280 | "debug": "^4.1.1",
2281 | "duplexify": "^4.1.1",
2282 | "help-me": "^3.0.0",
2283 | "inherits": "^2.0.3",
2284 | "lru-cache": "^6.0.0",
2285 | "minimist": "^1.2.5",
2286 | "mqtt-packet": "^6.8.0",
2287 | "number-allocator": "^1.0.9",
2288 | "pump": "^3.0.0",
2289 | "readable-stream": "^3.6.0",
2290 | "reinterval": "^1.1.0",
2291 | "rfdc": "^1.3.0",
2292 | "split2": "^3.1.0",
2293 | "ws": "^7.5.5",
2294 | "xtend": "^4.0.2"
2295 | }
2296 | },
2297 | "mqtt-packet": {
2298 | "version": "6.10.0",
2299 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
2300 | "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
2301 | "requires": {
2302 | "bl": "^4.0.2",
2303 | "debug": "^4.1.1",
2304 | "process-nextick-args": "^2.0.1"
2305 | }
2306 | },
2307 | "ms": {
2308 | "version": "2.1.3",
2309 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
2310 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
2311 | },
2312 | "natural-compare": {
2313 | "version": "1.4.0",
2314 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
2315 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
2316 | "dev": true
2317 | },
2318 | "number-allocator": {
2319 | "version": "1.0.14",
2320 | "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz",
2321 | "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
2322 | "requires": {
2323 | "debug": "^4.3.1",
2324 | "js-sdsl": "4.3.0"
2325 | }
2326 | },
2327 | "once": {
2328 | "version": "1.4.0",
2329 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
2330 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
2331 | "requires": {
2332 | "wrappy": "1"
2333 | }
2334 | },
2335 | "optionator": {
2336 | "version": "0.9.3",
2337 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
2338 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
2339 | "dev": true,
2340 | "requires": {
2341 | "@aashutoshrathi/word-wrap": "^1.2.3",
2342 | "deep-is": "^0.1.3",
2343 | "fast-levenshtein": "^2.0.6",
2344 | "levn": "^0.4.1",
2345 | "prelude-ls": "^1.2.1",
2346 | "type-check": "^0.4.0"
2347 | }
2348 | },
2349 | "parent-module": {
2350 | "version": "1.0.1",
2351 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
2352 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
2353 | "dev": true,
2354 | "requires": {
2355 | "callsites": "^3.0.0"
2356 | }
2357 | },
2358 | "parse-imports": {
2359 | "version": "2.1.1",
2360 | "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz",
2361 | "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==",
2362 | "dev": true,
2363 | "requires": {
2364 | "es-module-lexer": "^1.5.3",
2365 | "slashes": "^3.0.12"
2366 | }
2367 | },
2368 | "path-is-absolute": {
2369 | "version": "1.0.1",
2370 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
2371 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
2372 | },
2373 | "path-key": {
2374 | "version": "3.1.1",
2375 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
2376 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
2377 | "dev": true
2378 | },
2379 | "prelude-ls": {
2380 | "version": "1.2.1",
2381 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
2382 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
2383 | "dev": true
2384 | },
2385 | "process-nextick-args": {
2386 | "version": "2.0.1",
2387 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
2388 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
2389 | },
2390 | "pump": {
2391 | "version": "3.0.0",
2392 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
2393 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
2394 | "requires": {
2395 | "end-of-stream": "^1.1.0",
2396 | "once": "^1.3.1"
2397 | }
2398 | },
2399 | "punycode": {
2400 | "version": "2.3.0",
2401 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
2402 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
2403 | "dev": true
2404 | },
2405 | "readable-stream": {
2406 | "version": "3.6.2",
2407 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
2408 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
2409 | "requires": {
2410 | "inherits": "^2.0.3",
2411 | "string_decoder": "^1.1.1",
2412 | "util-deprecate": "^1.0.1"
2413 | }
2414 | },
2415 | "refa": {
2416 | "version": "0.9.1",
2417 | "resolved": "https://registry.npmjs.org/refa/-/refa-0.9.1.tgz",
2418 | "integrity": "sha512-egU8LgFq2VXlAfUi8Jcbr5X38wEOadMFf8tCbshgcpVCYlE7k84pJOSlnvXF+muDB4igkdVMq7Z/kiNPqDT9TA==",
2419 | "dev": true,
2420 | "requires": {
2421 | "regexpp": "^3.2.0"
2422 | }
2423 | },
2424 | "regexp-ast-analysis": {
2425 | "version": "0.5.1",
2426 | "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.5.1.tgz",
2427 | "integrity": "sha512-Ca/g9gaTNuMewLuu+mBIq4vCrGRSO8AE9bP32NMQjJ/wBTdWq0g96qLkBb0NbGwEbp7S/q+NQF3o7veeuRfg0g==",
2428 | "dev": true,
2429 | "requires": {
2430 | "refa": "^0.9.0",
2431 | "regexpp": "^3.2.0"
2432 | }
2433 | },
2434 | "regexpp": {
2435 | "version": "3.2.0",
2436 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
2437 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
2438 | "dev": true
2439 | },
2440 | "reinterval": {
2441 | "version": "1.1.0",
2442 | "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
2443 | "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
2444 | },
2445 | "requireindex": {
2446 | "version": "1.2.0",
2447 | "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
2448 | "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
2449 | "dev": true
2450 | },
2451 | "resolve-from": {
2452 | "version": "4.0.0",
2453 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2454 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2455 | "dev": true
2456 | },
2457 | "rfdc": {
2458 | "version": "1.3.0",
2459 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
2460 | "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
2461 | },
2462 | "rimraf": {
2463 | "version": "3.0.2",
2464 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
2465 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
2466 | "dev": true,
2467 | "requires": {
2468 | "glob": "^7.1.3"
2469 | }
2470 | },
2471 | "safe-buffer": {
2472 | "version": "5.2.1",
2473 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2474 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
2475 | },
2476 | "scslre": {
2477 | "version": "0.1.6",
2478 | "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.1.6.tgz",
2479 | "integrity": "sha512-JORxVRlQTfjvlOAaiQKebgFElyAm5/W8b50lgaZ0OkEnKnagJW2ufDh3xRfU75UD9z3FGIu1gL1IyR3Poa6Qmw==",
2480 | "dev": true,
2481 | "requires": {
2482 | "refa": "^0.9.0",
2483 | "regexp-ast-analysis": "^0.2.3",
2484 | "regexpp": "^3.2.0"
2485 | },
2486 | "dependencies": {
2487 | "regexp-ast-analysis": {
2488 | "version": "0.2.4",
2489 | "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.2.4.tgz",
2490 | "integrity": "sha512-8L7kOZQaKPxKKAwGuUZxTQtlO3WZ+tiXy4s6G6PKL6trbOXcZoumwC3AOHHFtI/xoSbNxt7jgLvCnP1UADLWqg==",
2491 | "dev": true,
2492 | "requires": {
2493 | "refa": "^0.9.0",
2494 | "regexpp": "^3.2.0"
2495 | }
2496 | }
2497 | }
2498 | },
2499 | "semver": {
2500 | "version": "7.6.3",
2501 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
2502 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
2503 | "dev": true
2504 | },
2505 | "shebang-command": {
2506 | "version": "2.0.0",
2507 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
2508 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
2509 | "dev": true,
2510 | "requires": {
2511 | "shebang-regex": "^3.0.0"
2512 | }
2513 | },
2514 | "shebang-regex": {
2515 | "version": "3.0.0",
2516 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
2517 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
2518 | "dev": true
2519 | },
2520 | "slashes": {
2521 | "version": "3.0.12",
2522 | "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz",
2523 | "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==",
2524 | "dev": true
2525 | },
2526 | "spdx-exceptions": {
2527 | "version": "2.5.0",
2528 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
2529 | "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
2530 | "dev": true
2531 | },
2532 | "spdx-expression-parse": {
2533 | "version": "4.0.0",
2534 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz",
2535 | "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==",
2536 | "dev": true,
2537 | "requires": {
2538 | "spdx-exceptions": "^2.1.0",
2539 | "spdx-license-ids": "^3.0.0"
2540 | }
2541 | },
2542 | "spdx-license-ids": {
2543 | "version": "3.0.20",
2544 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
2545 | "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
2546 | "dev": true
2547 | },
2548 | "split2": {
2549 | "version": "3.2.2",
2550 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
2551 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
2552 | "requires": {
2553 | "readable-stream": "^3.0.0"
2554 | }
2555 | },
2556 | "stream-shift": {
2557 | "version": "1.0.1",
2558 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
2559 | "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
2560 | },
2561 | "string_decoder": {
2562 | "version": "1.3.0",
2563 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
2564 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
2565 | "requires": {
2566 | "safe-buffer": "~5.2.0"
2567 | }
2568 | },
2569 | "strip-ansi": {
2570 | "version": "6.0.1",
2571 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
2572 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
2573 | "dev": true,
2574 | "requires": {
2575 | "ansi-regex": "^5.0.1"
2576 | }
2577 | },
2578 | "strip-json-comments": {
2579 | "version": "3.1.1",
2580 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
2581 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
2582 | "dev": true
2583 | },
2584 | "supports-color": {
2585 | "version": "7.2.0",
2586 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2587 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2588 | "dev": true,
2589 | "requires": {
2590 | "has-flag": "^4.0.0"
2591 | }
2592 | },
2593 | "synckit": {
2594 | "version": "0.9.1",
2595 | "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
2596 | "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
2597 | "dev": true,
2598 | "requires": {
2599 | "@pkgr/core": "^0.1.0",
2600 | "tslib": "^2.6.2"
2601 | }
2602 | },
2603 | "text-table": {
2604 | "version": "0.2.0",
2605 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
2606 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
2607 | "dev": true
2608 | },
2609 | "tslib": {
2610 | "version": "2.7.0",
2611 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
2612 | "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
2613 | "dev": true
2614 | },
2615 | "type-check": {
2616 | "version": "0.4.0",
2617 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
2618 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
2619 | "dev": true,
2620 | "requires": {
2621 | "prelude-ls": "^1.2.1"
2622 | }
2623 | },
2624 | "type-fest": {
2625 | "version": "0.20.2",
2626 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
2627 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
2628 | "dev": true
2629 | },
2630 | "typedarray": {
2631 | "version": "0.0.6",
2632 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
2633 | "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
2634 | },
2635 | "uri-js": {
2636 | "version": "4.4.1",
2637 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
2638 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
2639 | "dev": true,
2640 | "requires": {
2641 | "punycode": "^2.1.0"
2642 | }
2643 | },
2644 | "util-deprecate": {
2645 | "version": "1.0.2",
2646 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
2647 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
2648 | },
2649 | "v8-compile-cache": {
2650 | "version": "2.3.0",
2651 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
2652 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
2653 | "dev": true
2654 | },
2655 | "which": {
2656 | "version": "2.0.2",
2657 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
2658 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
2659 | "dev": true,
2660 | "requires": {
2661 | "isexe": "^2.0.0"
2662 | }
2663 | },
2664 | "wrappy": {
2665 | "version": "1.0.2",
2666 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
2667 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
2668 | },
2669 | "ws": {
2670 | "version": "7.5.10",
2671 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
2672 | "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
2673 | "requires": {}
2674 | },
2675 | "xtend": {
2676 | "version": "4.0.2",
2677 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
2678 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
2679 | },
2680 | "yallist": {
2681 | "version": "4.0.0",
2682 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
2683 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
2684 | }
2685 | }
2686 | }
2687 |
--------------------------------------------------------------------------------