├── frontend
├── .gitignore
├── package.json
├── index.js
├── src
│ └── render.js
├── index.html
└── package-lock.json
├── .gitattributes
├── readme.md
└── backend
└── app.py
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "python-electron-boilerplate-frontend",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "electron": "^11.1.1",
14 | "jquery": "^3.5.1",
15 | "time-stamp": "^2.2.0",
16 | "zeromq": "^6.0.0-beta.6"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/frontend/index.js:
--------------------------------------------------------------------------------
1 | const { app, BrowserWindow, ipcMain } = require('electron');
2 | const { join } = require('path');
3 |
4 | let mainWindow;
5 |
6 | const createWindow = () => {
7 | mainWindow = new BrowserWindow({
8 | webPreferences: {
9 | nodeIntegration: true,
10 | contextIsolation: false
11 | },
12 | show: true,
13 | devTools: true
14 | })
15 | mainWindow.setMenuBarVisibility(false);
16 | mainWindow.loadFile(join(__dirname + '/index.html'));
17 | }
18 |
19 | app.once("ready", createWindow);
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # python-electron-boilerplate
2 | python-electron-boilerplate is a boilerplate framework allowing you to create a multi-process application using Python as a backend and Node.JS and Electron on the frontend. ZeroMQ sockets are used to create communication channels. This is very barebones and merely displays the functionality that ZMQ can offer to communicate between processes.
3 | 
4 |
5 | ## Running
6 | Run app.py in the backend, and then start electron in the frontend directory.
7 |
8 | ## Contributing
9 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
10 |
11 | ## License
12 | [MIT](https://choosealicense.com/licenses/mit/)
13 |
--------------------------------------------------------------------------------
/frontend/src/render.js:
--------------------------------------------------------------------------------
1 | const ZMQ = require('zeromq');
2 | const $ = require('jquery');
3 | const ts = require('time-stamp');
4 | const { stringify } = JSON;
5 |
6 | const mainSock = new ZMQ.Push;
7 | const dataSock = new ZMQ.Request;
8 | const statusSock = new ZMQ.Pull;
9 |
10 | mainSock.connect("tcp://127.0.0.1:7777");
11 | dataSock.connect("tcp://127.0.0.1:7778");
12 | statusSock.connect("tcp://127.0.0.1:7779");
13 |
14 | $('#sendData').on("click", async() => {
15 | const sendData = $('#send-data').val();
16 | await mainSock.send(stringify({ type: "data", data: sendData }));
17 | })
18 |
19 | $('#sendReceiveData').on("click", async() => {
20 | const sendData = $('#send-receive-data').val();
21 | await dataSock.send(stringify({ type: "data", data: sendData }));
22 | const [dataResponse] = await dataSock.receive();
23 | $('#received-data').val(dataResponse.toString());
24 | })
25 |
26 | const checkStatus = async() => {
27 | for await(const [msg] of statusSock){
28 | $('#status-data').prepend(logTime(), " ", msg.toString(), "\n")
29 | }
30 | }
31 |
32 | checkStatus()
33 |
34 | const logTime = () => {
35 | return ts("HH:mm:ss");
36 | }
--------------------------------------------------------------------------------
/backend/app.py:
--------------------------------------------------------------------------------
1 | import zmq
2 | import signal
3 | from time import sleep
4 | from queue import Queue
5 | from random import choice
6 | from threading import Thread
7 | from json import loads, dumps
8 |
9 | statusQueue = Queue()
10 |
11 | statusMessages = [
12 | {"type": "general", "message": "testing"},
13 | {"type": "taskStatus", "message": "task 1 started"},
14 | {"type": "taskStatus", "message": "task 2 stopped"}
15 | ]
16 |
17 | def mainSocket():
18 | context = zmq.Context()
19 | socket = context.socket(zmq.PULL)
20 | socket.bind("tcp://*:7777")
21 |
22 | while True:
23 | message = loads(socket.recv())
24 | print(message)
25 |
26 | def dataSocket():
27 | context = zmq.Context()
28 | socket = context.socket(zmq.REP)
29 | socket.bind("tcp://*:7778")
30 |
31 | while True:
32 | message = loads(socket.recv())
33 | print(message)
34 | socket.send(dumps({"dataReceived": message}).encode())
35 |
36 | def statusSocket():
37 | context = zmq.Context()
38 | socket = context.socket(zmq.PUSH)
39 | socket.bind("tcp://*:7779")
40 |
41 | while True:
42 | status = statusQueue.get()
43 | socket.send_json(status)
44 |
45 | if __name__ == "__main__":
46 |
47 | signal.signal(signal.SIGINT, signal.SIG_DFL)
48 |
49 | Thread(target = mainSocket).start()
50 | Thread(target = dataSocket).start()
51 | Thread(target = statusSocket).start()
52 |
53 | while True:
54 | statusQueue.put(choice(statusMessages))
55 | sleep(5)
--------------------------------------------------------------------------------
/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Python Electron Boilerplate
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Python Electron Boilerplate
17 |
18 |
19 |
20 |
21 |
Send Data
22 |
This utilizes a ZMQ Push Socket in the frontend and a ZMQ Pull socket in the backend.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
Send/Receive Data
32 |
This utilizes a ZMQ Request Socket in the frontend and a ZMQ Reply socket in the backend.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Status Data
45 |
This utilizes a Queue and ZMQ Push Socket in the backend and a ZMQ Pull socket in the frontend.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/frontend/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "python-electron-boilerplate-frontend",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@electron/get": {
8 | "version": "1.12.2",
9 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.2.tgz",
10 | "integrity": "sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg==",
11 | "requires": {
12 | "debug": "^4.1.1",
13 | "env-paths": "^2.2.0",
14 | "fs-extra": "^8.1.0",
15 | "global-agent": "^2.0.2",
16 | "global-tunnel-ng": "^2.7.1",
17 | "got": "^9.6.0",
18 | "progress": "^2.0.3",
19 | "sanitize-filename": "^1.6.2",
20 | "sumchecker": "^3.0.1"
21 | }
22 | },
23 | "@sindresorhus/is": {
24 | "version": "0.14.0",
25 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
26 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ=="
27 | },
28 | "@szmarczak/http-timer": {
29 | "version": "1.1.2",
30 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
31 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
32 | "requires": {
33 | "defer-to-connect": "^1.0.1"
34 | }
35 | },
36 | "@types/node": {
37 | "version": "12.19.11",
38 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.11.tgz",
39 | "integrity": "sha512-bwVfNTFZOrGXyiQ6t4B9sZerMSShWNsGRw8tC5DY1qImUNczS9SjT4G6PnzjCnxsu5Ubj6xjL2lgwddkxtQl5w=="
40 | },
41 | "boolean": {
42 | "version": "3.0.2",
43 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz",
44 | "integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==",
45 | "optional": true
46 | },
47 | "buffer-crc32": {
48 | "version": "0.2.13",
49 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
50 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
51 | },
52 | "buffer-from": {
53 | "version": "1.1.1",
54 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
55 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
56 | },
57 | "cacheable-request": {
58 | "version": "6.1.0",
59 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
60 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
61 | "requires": {
62 | "clone-response": "^1.0.2",
63 | "get-stream": "^5.1.0",
64 | "http-cache-semantics": "^4.0.0",
65 | "keyv": "^3.0.0",
66 | "lowercase-keys": "^2.0.0",
67 | "normalize-url": "^4.1.0",
68 | "responselike": "^1.0.2"
69 | },
70 | "dependencies": {
71 | "get-stream": {
72 | "version": "5.2.0",
73 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
74 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
75 | "requires": {
76 | "pump": "^3.0.0"
77 | }
78 | },
79 | "lowercase-keys": {
80 | "version": "2.0.0",
81 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
82 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
83 | }
84 | }
85 | },
86 | "clone-response": {
87 | "version": "1.0.2",
88 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
89 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
90 | "requires": {
91 | "mimic-response": "^1.0.0"
92 | }
93 | },
94 | "concat-stream": {
95 | "version": "1.6.2",
96 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
97 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
98 | "requires": {
99 | "buffer-from": "^1.0.0",
100 | "inherits": "^2.0.3",
101 | "readable-stream": "^2.2.2",
102 | "typedarray": "^0.0.6"
103 | }
104 | },
105 | "config-chain": {
106 | "version": "1.1.12",
107 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
108 | "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
109 | "optional": true,
110 | "requires": {
111 | "ini": "^1.3.4",
112 | "proto-list": "~1.2.1"
113 | }
114 | },
115 | "core-js": {
116 | "version": "3.8.1",
117 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
118 | "integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==",
119 | "optional": true
120 | },
121 | "core-util-is": {
122 | "version": "1.0.2",
123 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
124 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
125 | },
126 | "debug": {
127 | "version": "4.3.1",
128 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
129 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
130 | "requires": {
131 | "ms": "2.1.2"
132 | }
133 | },
134 | "decompress-response": {
135 | "version": "3.3.0",
136 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
137 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
138 | "requires": {
139 | "mimic-response": "^1.0.0"
140 | }
141 | },
142 | "defer-to-connect": {
143 | "version": "1.1.3",
144 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
145 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
146 | },
147 | "define-properties": {
148 | "version": "1.1.3",
149 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
150 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
151 | "optional": true,
152 | "requires": {
153 | "object-keys": "^1.0.12"
154 | }
155 | },
156 | "detect-node": {
157 | "version": "2.0.4",
158 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
159 | "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
160 | "optional": true
161 | },
162 | "duplexer3": {
163 | "version": "0.1.4",
164 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
165 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
166 | },
167 | "electron": {
168 | "version": "11.1.1",
169 | "resolved": "https://registry.npmjs.org/electron/-/electron-11.1.1.tgz",
170 | "integrity": "sha512-tlbex3xosJgfileN6BAQRotevPRXB/wQIq48QeQ08tUJJrXwE72c8smsM/hbHx5eDgnbfJ2G3a60PmRjHU2NhA==",
171 | "requires": {
172 | "@electron/get": "^1.0.1",
173 | "@types/node": "^12.0.12",
174 | "extract-zip": "^1.0.3"
175 | }
176 | },
177 | "encodeurl": {
178 | "version": "1.0.2",
179 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
180 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
181 | "optional": true
182 | },
183 | "end-of-stream": {
184 | "version": "1.4.4",
185 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
186 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
187 | "requires": {
188 | "once": "^1.4.0"
189 | }
190 | },
191 | "env-paths": {
192 | "version": "2.2.0",
193 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
194 | "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA=="
195 | },
196 | "es6-error": {
197 | "version": "4.1.1",
198 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
199 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
200 | "optional": true
201 | },
202 | "escape-string-regexp": {
203 | "version": "4.0.0",
204 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
205 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
206 | "optional": true
207 | },
208 | "extract-zip": {
209 | "version": "1.7.0",
210 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
211 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
212 | "requires": {
213 | "concat-stream": "^1.6.2",
214 | "debug": "^2.6.9",
215 | "mkdirp": "^0.5.4",
216 | "yauzl": "^2.10.0"
217 | },
218 | "dependencies": {
219 | "debug": {
220 | "version": "2.6.9",
221 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
222 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
223 | "requires": {
224 | "ms": "2.0.0"
225 | }
226 | },
227 | "ms": {
228 | "version": "2.0.0",
229 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
230 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
231 | }
232 | }
233 | },
234 | "fd-slicer": {
235 | "version": "1.1.0",
236 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
237 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
238 | "requires": {
239 | "pend": "~1.2.0"
240 | }
241 | },
242 | "fs-extra": {
243 | "version": "8.1.0",
244 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
245 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
246 | "requires": {
247 | "graceful-fs": "^4.2.0",
248 | "jsonfile": "^4.0.0",
249 | "universalify": "^0.1.0"
250 | }
251 | },
252 | "get-stream": {
253 | "version": "4.1.0",
254 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
255 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
256 | "requires": {
257 | "pump": "^3.0.0"
258 | }
259 | },
260 | "global-agent": {
261 | "version": "2.1.12",
262 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz",
263 | "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==",
264 | "optional": true,
265 | "requires": {
266 | "boolean": "^3.0.1",
267 | "core-js": "^3.6.5",
268 | "es6-error": "^4.1.1",
269 | "matcher": "^3.0.0",
270 | "roarr": "^2.15.3",
271 | "semver": "^7.3.2",
272 | "serialize-error": "^7.0.1"
273 | }
274 | },
275 | "global-tunnel-ng": {
276 | "version": "2.7.1",
277 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
278 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
279 | "optional": true,
280 | "requires": {
281 | "encodeurl": "^1.0.2",
282 | "lodash": "^4.17.10",
283 | "npm-conf": "^1.1.3",
284 | "tunnel": "^0.0.6"
285 | }
286 | },
287 | "globalthis": {
288 | "version": "1.0.1",
289 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz",
290 | "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==",
291 | "optional": true,
292 | "requires": {
293 | "define-properties": "^1.1.3"
294 | }
295 | },
296 | "got": {
297 | "version": "9.6.0",
298 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
299 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
300 | "requires": {
301 | "@sindresorhus/is": "^0.14.0",
302 | "@szmarczak/http-timer": "^1.1.2",
303 | "cacheable-request": "^6.0.0",
304 | "decompress-response": "^3.3.0",
305 | "duplexer3": "^0.1.4",
306 | "get-stream": "^4.1.0",
307 | "lowercase-keys": "^1.0.1",
308 | "mimic-response": "^1.0.1",
309 | "p-cancelable": "^1.0.0",
310 | "to-readable-stream": "^1.0.0",
311 | "url-parse-lax": "^3.0.0"
312 | }
313 | },
314 | "graceful-fs": {
315 | "version": "4.2.4",
316 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
317 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
318 | },
319 | "http-cache-semantics": {
320 | "version": "4.1.0",
321 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
322 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
323 | },
324 | "inherits": {
325 | "version": "2.0.4",
326 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
327 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
328 | },
329 | "ini": {
330 | "version": "1.3.8",
331 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
332 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
333 | "optional": true
334 | },
335 | "isarray": {
336 | "version": "1.0.0",
337 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
338 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
339 | },
340 | "jquery": {
341 | "version": "3.5.1",
342 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
343 | "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
344 | },
345 | "json-buffer": {
346 | "version": "3.0.0",
347 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
348 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
349 | },
350 | "json-stringify-safe": {
351 | "version": "5.0.1",
352 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
353 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
354 | "optional": true
355 | },
356 | "jsonfile": {
357 | "version": "4.0.0",
358 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
359 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
360 | "requires": {
361 | "graceful-fs": "^4.1.6"
362 | }
363 | },
364 | "keyv": {
365 | "version": "3.1.0",
366 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
367 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
368 | "requires": {
369 | "json-buffer": "3.0.0"
370 | }
371 | },
372 | "lodash": {
373 | "version": "4.17.20",
374 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
375 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
376 | "optional": true
377 | },
378 | "lowercase-keys": {
379 | "version": "1.0.1",
380 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
381 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
382 | },
383 | "lru-cache": {
384 | "version": "6.0.0",
385 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
386 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
387 | "optional": true,
388 | "requires": {
389 | "yallist": "^4.0.0"
390 | }
391 | },
392 | "matcher": {
393 | "version": "3.0.0",
394 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
395 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
396 | "optional": true,
397 | "requires": {
398 | "escape-string-regexp": "^4.0.0"
399 | }
400 | },
401 | "mimic-response": {
402 | "version": "1.0.1",
403 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
404 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
405 | },
406 | "minimist": {
407 | "version": "1.2.5",
408 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
409 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
410 | },
411 | "mkdirp": {
412 | "version": "0.5.5",
413 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
414 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
415 | "requires": {
416 | "minimist": "^1.2.5"
417 | }
418 | },
419 | "ms": {
420 | "version": "2.1.2",
421 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
422 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
423 | },
424 | "node-gyp-build": {
425 | "version": "4.2.3",
426 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
427 | "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
428 | },
429 | "normalize-url": {
430 | "version": "4.5.0",
431 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
432 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
433 | },
434 | "npm-conf": {
435 | "version": "1.1.3",
436 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
437 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
438 | "optional": true,
439 | "requires": {
440 | "config-chain": "^1.1.11",
441 | "pify": "^3.0.0"
442 | }
443 | },
444 | "object-keys": {
445 | "version": "1.1.1",
446 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
447 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
448 | "optional": true
449 | },
450 | "once": {
451 | "version": "1.4.0",
452 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
453 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
454 | "requires": {
455 | "wrappy": "1"
456 | }
457 | },
458 | "p-cancelable": {
459 | "version": "1.1.0",
460 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
461 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw=="
462 | },
463 | "pend": {
464 | "version": "1.2.0",
465 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
466 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
467 | },
468 | "pify": {
469 | "version": "3.0.0",
470 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
471 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
472 | "optional": true
473 | },
474 | "prepend-http": {
475 | "version": "2.0.0",
476 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
477 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
478 | },
479 | "process-nextick-args": {
480 | "version": "2.0.1",
481 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
482 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
483 | },
484 | "progress": {
485 | "version": "2.0.3",
486 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
487 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
488 | },
489 | "proto-list": {
490 | "version": "1.2.4",
491 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
492 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
493 | "optional": true
494 | },
495 | "pump": {
496 | "version": "3.0.0",
497 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
498 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
499 | "requires": {
500 | "end-of-stream": "^1.1.0",
501 | "once": "^1.3.1"
502 | }
503 | },
504 | "readable-stream": {
505 | "version": "2.3.7",
506 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
507 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
508 | "requires": {
509 | "core-util-is": "~1.0.0",
510 | "inherits": "~2.0.3",
511 | "isarray": "~1.0.0",
512 | "process-nextick-args": "~2.0.0",
513 | "safe-buffer": "~5.1.1",
514 | "string_decoder": "~1.1.1",
515 | "util-deprecate": "~1.0.1"
516 | }
517 | },
518 | "responselike": {
519 | "version": "1.0.2",
520 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
521 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
522 | "requires": {
523 | "lowercase-keys": "^1.0.0"
524 | }
525 | },
526 | "roarr": {
527 | "version": "2.15.4",
528 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
529 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
530 | "optional": true,
531 | "requires": {
532 | "boolean": "^3.0.1",
533 | "detect-node": "^2.0.4",
534 | "globalthis": "^1.0.1",
535 | "json-stringify-safe": "^5.0.1",
536 | "semver-compare": "^1.0.0",
537 | "sprintf-js": "^1.1.2"
538 | }
539 | },
540 | "safe-buffer": {
541 | "version": "5.1.2",
542 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
543 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
544 | },
545 | "sanitize-filename": {
546 | "version": "1.6.3",
547 | "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
548 | "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
549 | "requires": {
550 | "truncate-utf8-bytes": "^1.0.0"
551 | }
552 | },
553 | "semver": {
554 | "version": "7.3.4",
555 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
556 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
557 | "optional": true,
558 | "requires": {
559 | "lru-cache": "^6.0.0"
560 | }
561 | },
562 | "semver-compare": {
563 | "version": "1.0.0",
564 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
565 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
566 | "optional": true
567 | },
568 | "serialize-error": {
569 | "version": "7.0.1",
570 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
571 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
572 | "optional": true,
573 | "requires": {
574 | "type-fest": "^0.13.1"
575 | }
576 | },
577 | "sprintf-js": {
578 | "version": "1.1.2",
579 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
580 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
581 | "optional": true
582 | },
583 | "string_decoder": {
584 | "version": "1.1.1",
585 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
586 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
587 | "requires": {
588 | "safe-buffer": "~5.1.0"
589 | }
590 | },
591 | "sumchecker": {
592 | "version": "3.0.1",
593 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
594 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
595 | "requires": {
596 | "debug": "^4.1.0"
597 | }
598 | },
599 | "time-stamp": {
600 | "version": "2.2.0",
601 | "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.2.0.tgz",
602 | "integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA=="
603 | },
604 | "to-readable-stream": {
605 | "version": "1.0.0",
606 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
607 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q=="
608 | },
609 | "truncate-utf8-bytes": {
610 | "version": "1.0.2",
611 | "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
612 | "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=",
613 | "requires": {
614 | "utf8-byte-length": "^1.0.1"
615 | }
616 | },
617 | "tunnel": {
618 | "version": "0.0.6",
619 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
620 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
621 | "optional": true
622 | },
623 | "type-fest": {
624 | "version": "0.13.1",
625 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
626 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
627 | "optional": true
628 | },
629 | "typedarray": {
630 | "version": "0.0.6",
631 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
632 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
633 | },
634 | "universalify": {
635 | "version": "0.1.2",
636 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
637 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
638 | },
639 | "url-parse-lax": {
640 | "version": "3.0.0",
641 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
642 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
643 | "requires": {
644 | "prepend-http": "^2.0.0"
645 | }
646 | },
647 | "utf8-byte-length": {
648 | "version": "1.0.4",
649 | "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
650 | "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E="
651 | },
652 | "util-deprecate": {
653 | "version": "1.0.2",
654 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
655 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
656 | },
657 | "wrappy": {
658 | "version": "1.0.2",
659 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
660 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
661 | },
662 | "yallist": {
663 | "version": "4.0.0",
664 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
665 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
666 | "optional": true
667 | },
668 | "yauzl": {
669 | "version": "2.10.0",
670 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
671 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
672 | "requires": {
673 | "buffer-crc32": "~0.2.3",
674 | "fd-slicer": "~1.1.0"
675 | }
676 | },
677 | "zeromq": {
678 | "version": "6.0.0-beta.6",
679 | "resolved": "https://registry.npmjs.org/zeromq/-/zeromq-6.0.0-beta.6.tgz",
680 | "integrity": "sha512-wLf6M7pBHijl+BRltUL2VoDpgbQcOZetiX8UzycHL8CcYFxYnRrpoG5fi3UX3+Umavz1lk4/dGaQez8qiDgr/Q==",
681 | "requires": {
682 | "node-gyp-build": "^4.1.0"
683 | }
684 | }
685 | }
686 | }
687 |
--------------------------------------------------------------------------------