10 Commits

Author SHA1 Message Date
Scott Idem
80b9c29cb1 Work on Electron 2022-04-16 19:25:09 -04:00
Scott Idem
c156852cb2 Work on a package.json 2022-04-16 18:50:03 -04:00
Scott Idem
4aec075855 Work on a package.json 2022-04-16 18:44:49 -04:00
Scott Idem
843755fc00 Work on a little bit of everything 2022-04-16 18:35:06 -04:00
Scott Idem
d17d475dba Work on launcher and config 2022-04-16 18:14:07 -04:00
Scott Idem
7c13beea0a Work on loading the config 2022-04-16 18:02:25 -04:00
Scott Idem
69f87fad35 Work on configs 2022-04-16 17:24:03 -04:00
Scott Idem
e0be599146 Work on launcher and config 2022-04-16 16:37:31 -04:00
Scott Idem
01746ec98d Work on launcher and config 2022-04-16 16:25:53 -04:00
Scott Idem
4b28c16996 Cleaning up the native launcher for first testing... 2022-04-13 17:15:46 -04:00
7 changed files with 2393 additions and 162 deletions

View File

@@ -21,13 +21,13 @@
<!-- One Sky IT site custom Cascading Style Sheets (CSS) --> <!-- One Sky IT site custom Cascading Style Sheets (CSS) -->
<link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_variables.css"> <link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_variables.css">
<link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_utilities.css"> <link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/svelte/build/aether_utilities.css">
<link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_system.css"> <link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_system.css">
<!-- <link rel="stylesheet" href="svelte/build/aether_layout.css"> --> <!-- <link rel="stylesheet" href="svelte/build/aether_layout.css"> -->
<!-- <link rel="stylesheet" href="css/aether_layout_flow.css"> --> <!-- <link rel="stylesheet" href="css/aether_layout_flow.css"> -->
<!-- <link rel="stylesheet" href="css/aether_layout_grid.css"> --> <!-- <link rel="stylesheet" href="css/aether_layout_grid.css"> -->
<link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_modules_core.css"> <link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/svelte/build/aether_modules_core.css">
<link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/css/aether_modules_other.css"> <!-- <link rel="stylesheet" href="http://dev.oneskyit.local:5000/static/svelte/build/aether_modules_other.css"> -->
<link href="http://dev.oneskyit.local:5000/static/svelte/build/bundle.css" rel="stylesheet"> <link href="http://dev.oneskyit.local:5000/static/svelte/build/bundle.css" rel="stylesheet">
<link href="http://dev.oneskyit.local:5000/static/svelte/build/reloading.css" rel="stylesheet"> <link href="http://dev.oneskyit.local:5000/static/svelte/build/reloading.css" rel="stylesheet">
@@ -35,7 +35,7 @@
<link href="http://dev.oneskyit.local:5000/static/css/base_style_grid_layout_v3.css" rel="stylesheet"> <link href="http://dev.oneskyit.local:5000/static/css/base_style_grid_layout_v3.css" rel="stylesheet">
<link href="http://dev.oneskyit.local:5000/static/css/base_style_grid_theme_v3.css" rel="stylesheet"> <link href="http://dev.oneskyit.local:5000/static/css/base_style_grid_theme_v3.css" rel="stylesheet">
<link href="http://dev.oneskyit.local:5000/event/assets/css/event_launcher.css" rel="stylesheet"> <link href="http://dev.oneskyit.local:5000/static/svelte/build/event_launcher.css" rel="stylesheet">
<link rel="stylesheet" href="css/aether_native_app_v3.css"> <link rel="stylesheet" href="css/aether_native_app_v3.css">
@@ -57,9 +57,10 @@
<script src="https://static.oneskyit.com/js/utilities.js"></script> <script src="https://static.oneskyit.com/js/utilities.js"></script>
<!-- <script src="js/app_idb.js"></script> --> <!-- <script src="js/app_idb.js"></script> -->
<script>const app = require('./js/aether_native_app_v3');</script>
<script> <script>
const app = require('./js/aether_native_app_v3');
let app_config = app.load_config(); let app_config = app.load_config();
console.log(app_config);
const flask_env = 'development'; // 'development', 'production' const flask_env = 'development'; // 'development', 'production'
const env = 'development'; // 'development', 'production' const env = 'development'; // 'development', 'production'
@@ -76,13 +77,37 @@
const page_for = { 'event': event_id, 'event_device': event_device_id, 'event_location': event_location_id }; // Simple key value like object const page_for = { 'event': event_id, 'event_device': event_device_id, 'event_location': event_location_id }; // Simple key value like object
console.log(page_for); console.log(page_for);
const host_file_cache_path = 'file_cache'; // app_config.host_file_cache_path; // 'file_cache/' const host_file_cache_path = app_config.host_file_cache_path; // 'file_cache/'
console.log(host_file_cache_path); // console.log(host_file_cache_path);
const host_file_temp_path = 'temp' // app_config.host_file_temp_path; // 'temp/' const host_file_temp_path = app_config.host_file_temp_path; // 'temp/'
console.log(host_file_temp_path); // console.log(host_file_temp_path);
let idb_name = app_config.idb_name; let idb_name = app_config.idb_name;
// BEGIN: API section
const access_control_allow_origin = app_config.access_control_allow_origin;
const api_secret_key = app_config.api_secret_key;
console.log(api_secret_key);
let api_temporary_token = null;
let api_base_url = null;
if (app_config.use_local_api) {
api_base_url = app_config.api_local_base_url; // 'http://api.localhost:5001'
} else {
api_base_url = app_config.api_remote_base_url; // 'https://api.oneskyit.com'
}
/* ***** **** *** ** * ### * ** *** **** ***** */
let app_online = false;
//let app_use_cached_data = true;
window.addEventListener('online', app.currently_online);
window.addEventListener('offline', app.currently_offline);
/* ***** **** *** ** * ### * ** *** **** ***** */
</script> </script>
<!-- <script defer src="svelte/build/bundle.js" crossorigin></script> --> <!-- <script defer src="svelte/build/bundle.js" crossorigin></script> -->
@@ -120,29 +145,9 @@
<script> <script>
/* ***** **** *** ** * ### * ** *** **** ***** */ /* ***** **** *** ** * ### * ** *** **** ***** */
// BEGIN: API section
const access_control_allow_origin = app_config.access_control_allow_origin;
const api_secret_key = app_config.api_secret_key;
console.log(api_secret_key);
let api_temporary_token = null;
let api_base_url = null;
if (app_config.use_local_api) {
api_base_url = app_config.api_local_base_url; // 'http://api.localhost:5001'
} else {
api_base_url = app_config.api_remote_base_url; // 'https://api.oneskyit.com'
}
/* ***** **** *** ** * ### * ** *** **** ***** */
let app_online = false;
//let app_use_cached_data = true;
window.addEventListener('online', app.currently_online);
window.addEventListener('offline', app.currently_offline);
/* ***** **** *** ** * ### * ** *** **** ***** */
// BEGIN: Load IDB section // BEGIN: Load IDB section
// let idb_name = app_config.idb_name; // let idb_name = app_config.idb_name;

View File

@@ -4,22 +4,30 @@ const path = require('path');
const fs = require('fs'); const fs = require('fs');
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron');
let home_directory = require('os').homedir();
console.log('Home: '+home_directory);
let tmp_directory = require('os').tmpdir();
console.log('Temporary: '+tmp_directory);
let config = null;
exports.load_config = function () { exports.load_config = function () {
console.log('*** Electron framework: load_config() ***'); console.log('*** Electron framework: load_config() ***');
console.log('CWD: '+process.cwd()); console.log('CWD: '+process.cwd());
let home_directory = require('os').homedir(); // let home_directory = require('os').homedir();
console.log('Home: '+home_directory); // console.log('Home: '+home_directory);
let tmp_directory = require('os').tmpdir(); // let tmp_directory = require('os').tmpdir();
console.log('Temporary: '+tmp_directory); // console.log('Temporary: '+tmp_directory);
let config = null; // let config = null;
let config_directory = null; let config_directory = null;
let default_config_path = path.join(process.cwd(),'config.json.default'); let default_config_path = path.join(process.cwd(),'config.json.default');
let config_path = null; let config_path = null;
// Set the config path for macOS or Linux
if (os.platform == 'darwin') { if (os.platform == 'darwin') {
config_directory = path.join(home_directory, 'Library/Application Support/OSIT'); config_directory = path.join(home_directory, 'Library/Application Support/OSIT');
console.log('macOS config directory: '+config_directory); console.log('macOS config directory: '+config_directory);
@@ -28,6 +36,7 @@ exports.load_config = function () {
console.log('Linux config directory: '+config_directory); console.log('Linux config directory: '+config_directory);
} }
// Look for the config file and copy the default if not found.
if (fs.existsSync(config_directory)) { if (fs.existsSync(config_directory)) {
console.log('Config: '+config_directory); console.log('Config: '+config_directory);
config_path = path.join(config_directory, 'config.json'); config_path = path.join(config_directory, 'config.json');
@@ -41,6 +50,7 @@ exports.load_config = function () {
console.log('Default config file copied: '+config_directory); console.log('Default config file copied: '+config_directory);
} }
// Attempt to open the config file. The preferred location is based on the OS's config directory.
if (fs.existsSync(config_path)) { if (fs.existsSync(config_path)) {
console.log('Config path: '+config_path); console.log('Config path: '+config_path);
console.log('Config file (config.json) found under '+config_directory+'.'); console.log('Config file (config.json) found under '+config_directory+'.');
@@ -66,6 +76,21 @@ exports.load_config = function () {
} else { } else {
//close(); //close();
} }
config.host_file_cache_path = config.host_file_cache_path.replace('[home]', home_directory);
config.host_file_cache_path = config.host_file_cache_path.replace('[tmp]', tmp_directory);
console.log(config.host_file_cache_path);
config.host_file_temp_path = config.host_file_temp_path.replace('[home]', home_directory);
config.host_file_temp_path = config.host_file_temp_path.replace('[tmp]', tmp_directory);
console.log(config.host_file_temp_path);
let import_config_to_ipc_result = ipcRenderer.invoke('import_config', config).then((result) => {
console.log('IPC import config finished');
console.log(result);
return true;
})
//console.log(config); //console.log(config);
return config; return config;
} }

View File

@@ -7,29 +7,15 @@
"event_presentation_id": null, "event_presentation_id": null,
"event_presenter_id": null, "event_presenter_id": null,
"event_file_id": null, "event_file_id": null,
"api_auth_loop_interval": 100,
"api_token_update_loop_interval": 120000,
"open_tables_loop_interval": 10,
"update_idb_loop_interval": 10,
"idb_to_launcher_loop_interval": 250,
"update_render_loop_interval": 1000,
"check_file_cache_loop_interval": 250,
"api_secret_key": "dFP6J9DVj9hUgIMn-fNIqg", "api_secret_key": "dFP6J9DVj9hUgIMn-fNIqg",
"use_local_api": true,
"use_local_db": false,
"api_remote_base_url": "https://dev-fastapi.oneskyit.com", "api_remote_base_url": "https://dev-fastapi.oneskyit.com",
"api_local_base_url": "http://dev-fastapi.oneskyit.local:5005", "api_local_base_url": "http://dev-fastapi.oneskyit.local:5005",
"access_control_allow_origin": "*", "access_control_allow_origin": "*",
"remote_db_server": "db.oneskyit.com",
"remote_db_port": "3306", "use_local_api": true,
"remote_db_name": "onesky_ams_test", "use_local_db": false,
"remote_db_username": "username_here",
"remote_db_password": "password_here",
"local_db_server": "db.oneskyit.local",
"local_db_port": "3306",
"local_db_name": "onesky_ams_test",
"local_db_username": "username_here",
"local_db_password": "password_here",
"idb_name": "osit", "idb_name": "osit",
"idb_event_check_period": 120000, "idb_event_check_period": 120000,
"idb_event_location_check_period": 90000, "idb_event_location_check_period": 90000,
@@ -37,9 +23,31 @@
"idb_event_presentation_check_period": 90000, "idb_event_presentation_check_period": 90000,
"idb_event_presenter_check_period": 60000, "idb_event_presenter_check_period": 60000,
"idb_event_file_check_period": 30000, "idb_event_file_check_period": 30000,
"host_file_cache_path": "file_cache",
"host_file_cache_path": "[home]/tmp/OSIT/file_cache",
"host_file_cache_check_period": 30000, "host_file_cache_check_period": 30000,
"host_file_temp_path": "temp", "host_file_temp_path": "[home]/tmp/OSIT/temp",
"main_loop_interval": 2000,
"api_token_loop_interval": 1000,
"api_update_period": 90000,
"api_auth_loop_interval": 100,
"api_token_update_loop_interval": 120000,
"open_tables_loop_interval": 10,
"update_idb_loop_interval": 10,
"idb_to_launcher_loop_interval": 250,
"update_render_loop_interval": 1000,
"check_file_cache_loop_interval": 250,
"display_menu_session_times": true,
"display_session_codes": true,
"display_session_badges": true,
"display_presentation_codes": true,
"display_presentation_badges": true,
"display_presenter_codes": true,
"display_presenter_badges": true,
"display_arrangement": "mirror_and_extend", "display_arrangement": "mirror_and_extend",
"display_builtin_resolution": "", "display_builtin_resolution": "",
"display_builtin_refresh": "", "display_builtin_refresh": "",
@@ -47,8 +55,10 @@
"display_external_resolution": "", "display_external_resolution": "",
"display_external_refresh": "", "display_external_refresh": "",
"display_external_rotation": "", "display_external_rotation": "",
"audio_out_volume": null, "audio_out_volume": null,
"audio_in_volume": null, "audio_in_volume": null,
"recording_fps": 30, "recording_fps": 30,
"recording_show_cursor": true, "recording_show_cursor": true,
"recording_highlight_clicks": false, "recording_highlight_clicks": false,

View File

@@ -1,39 +1,42 @@
{ {
"account_id": "_XY7DXtc9MY", "account_id": "",
"event_id": "pjrcghqwert", "event_id": "",
"event_location_id": "LUNt2zdMKCUNb9VReMZu8A", "event_device_id": "",
"main_loop_interval": 2000, "event_location_id": "",
"api_token_loop_interval": 1000, "event_session_id": "",
"api_update_period": 90000,
"api_secret_key": "dFP6J9DVj9hUgIMn-fNIqg", "api_secret_key": "XXXXXX",
"use_local_api": true,
"use_local_db": false,
"api_remote_base_url": "https://dev-fastapi.oneskyit.com", "api_remote_base_url": "https://dev-fastapi.oneskyit.com",
"api_local_base_url": "http://dev-fastapi.oneskyit.local:5005", "api_local_base_url": "http://dev-fastapi.oneskyit.local:5005",
"access_control_allow_origin": "*", "access_control_allow_origin": "*",
"remote_db_server": "linode.oneskyit.com",
"remote_db_port": "3306", "use_local_api": true,
"remote_db_name": "onesky_ams_test", "use_local_db": false,
"remote_db_username": "username_here",
"remote_db_password": "password_here",
"local_db_server": "db.oneskyit.local",
"local_db_port": "3306",
"local_db_name": "onesky_ams_test",
"local_db_username": "username_here",
"local_db_password": "password_here",
"update_idb_loop_interval": 1000,
"idb_name": "osit", "idb_name": "osit",
"idb_check_period": 30000,
"idb_event_check_period": 120000, "idb_event_check_period": 120000,
"idb_event_location_check_period": 90000, "idb_event_location_check_period": 90000,
"idb_event_session_check_period": 60000, "idb_event_session_check_period": 90000,
"idb_event_presentation_check_period": 60000, "idb_event_presentation_check_period": 90000,
"idb_event_presenter_check_period": 60000, "idb_event_presenter_check_period": 60000,
"idb_event_file_check_period": 60000, "idb_event_file_check_period": 30000,
"check_file_cache_loop_interval": 250,
"host_file_cache_path": "file_cache", "host_file_cache_path": "[home]/OSIT/file_cache",
"host_file_cache_check_period": 30000, "host_file_cache_check_period": 30000,
"host_file_temp_path": "[home]/OSIT/temp",
"main_loop_interval": 2000,
"api_token_loop_interval": 1000,
"api_update_period": 90000,
"api_auth_loop_interval": 100,
"api_token_update_loop_interval": 120000,
"open_tables_loop_interval": 10,
"update_idb_loop_interval": 10,
"idb_to_launcher_loop_interval": 250,
"update_render_loop_interval": 1000, "update_render_loop_interval": 1000,
"check_file_cache_loop_interval": 250,
"display_menu_session_times": true, "display_menu_session_times": true,
"display_session_codes": true, "display_session_codes": true,
"display_session_badges": true, "display_session_badges": true,
@@ -41,6 +44,7 @@
"display_presentation_badges": true, "display_presentation_badges": true,
"display_presenter_codes": true, "display_presenter_codes": true,
"display_presenter_badges": true, "display_presenter_badges": true,
"display_arrangement": "mirror_and_extend", "display_arrangement": "mirror_and_extend",
"display_builtin_resolution": "", "display_builtin_resolution": "",
"display_builtin_refresh": "", "display_builtin_refresh": "",
@@ -48,18 +52,20 @@
"display_external_resolution": "", "display_external_resolution": "",
"display_external_refresh": "", "display_external_refresh": "",
"display_external_rotation": "", "display_external_rotation": "",
"audio_out_volume": null, "audio_out_volume": null,
"audio_in_volume": null, "audio_in_volume": null,
"fps": 30,
"show_cursor": true, "recording_fps": 30,
"highlight_clicks": false, "recording_show_cursor": true,
"screen_id": null, "recording_highlight_clicks": false,
"audio_device_id": null, "recording_screen_id": null,
"recording_audio_device_id": null,
"known_builtin_screen_ids": [69732032, 69733952, 69733248], "known_builtin_screen_ids": [69732032, 69733952, 69733248],
"known_builtin_audio_device_ids": [ "AppleHDAEngineInput:1B,0,1,0:1", "BuiltInMicrophoneDevice" ], "known_builtin_audio_device_ids": [ "AppleHDAEngineInput:1B,0,1,0:1", "BuiltInMicrophoneDevice" ],
"video_codec": "h264", "recording_video_codec": "h264",
"recordings_path": "[home]/recordings", "recording_path": "[home]/recordings",
"base_filename": "recording", "recording_base_filename": "recording",
"aperture_bin_path": null, "aperture_bin_path": null,
"recording_start_datetime": "2019-10-12 01:01:01Z", "recording_start_datetime": "2019-10-12 01:01:01Z",
"recording_stop_datetime": "2019-10-31 23:59:59Z", "recording_stop_datetime": "2019-10-31 23:59:59Z",

View File

@@ -11,6 +11,16 @@ const process = require('process');
//const url = require('url'); //const url = require('url');
// const usb = require('usb') // Compiled with an old version of Node.js // const usb = require('usb') // Compiled with an old version of Node.js
let home_directory = require('os').homedir();
console.log('Home: '+home_directory);
let tmp_directory = require('os').tmpdir();
console.log('Temporary: '+tmp_directory);
let config = null;
let host_file_cache_path = null;
let host_file_temp_path = null;
console.log(os.type()); console.log(os.type());
console.log(process.getSystemVersion()); console.log(process.getSystemVersion());
@@ -97,6 +107,37 @@ app.on('activate', () => {
}) })
// Import config data
// Updated 2022-04-16
ipcMain.handle('import_config', async (event, config_data) => {
console.log('*** Electron IPC Main: import_config() ***');
// console.log('ipcMain on download_file: api_base_url='+api_base_url+' | api_temporary_token='+api_temporary_token);
console.log('ipcMain on import_config:');
console.log(config_data);
config = config_data;
host_file_cache_path = config.host_file_cache_path;
host_file_temp_path = config.host_file_temp_path;
if (fs.existsSync(host_file_cache_path)) {
console.log('Host file cache path exists: '+host_file_cache_path);
} else {
fs.mkdirSync(host_file_cache_path, true);
console.log('Host file cache path created: '+host_file_cache_path);
}
if (fs.existsSync(host_file_temp_path)) {
console.log('Host file temp path exists: '+host_file_temp_path);
} else {
fs.mkdirSync(host_file_temp_path, true);
console.log('Host file temp path created: '+host_file_temp_path);
}
return true;
});
// Download file to path // Download file to path
// full_save_path should be the full path that includes the filename // full_save_path should be the full path that includes the filename
// Updated 2022-03-09 // Updated 2022-03-09
@@ -122,10 +163,10 @@ async function download_file(api_base_url, api_endpoint, full_save_path) {
console.log('*** node.js: download_file() ***'); console.log('*** node.js: download_file() ***');
axios.defaults.baseURL = api_base_url; axios.defaults.baseURL = api_base_url;
axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; // app_config.access_control_allow_origin; axios.defaults.headers.common['Access-Control-Allow-Origin'] = config.access_control_allow_origin; // '*'; // app_config.access_control_allow_origin;
axios.defaults.headers.common['content-type'] = 'application/json'; axios.defaults.headers.common['content-type'] = 'application/json';
axios.defaults.headers.common['x-aether-api-key'] = 'dFP6J9DVj9hUgIMn-fNIqg'; // api_secret_key; axios.defaults.headers.common['x-aether-api-key'] = config.api_secret_key; // 'dFP6J9DVj9hUgIMn-fNIqg'; // api_secret_key;
axios.defaults.headers.common['x-account-id'] = '_XY7DXtc9MY'; // account_id; axios.defaults.headers.common['x-account-id'] = config.account_id; // '_XY7DXtc9MY'; // account_id;
const url = api_endpoint; const url = api_endpoint;
@@ -188,14 +229,18 @@ ipcMain.handle('open_hash_file_to_temp', async (event, host_file_cache_path, has
console.log('ipcMain on open_hash_file_to_temp'); console.log('ipcMain on open_hash_file_to_temp');
console.log(`ipcMain open hash file from temp directory: ${host_file_cache_path} -> ${host_file_temp_path}/${filename}`); console.log(`ipcMain open hash file from temp directory: ${host_file_cache_path} -> ${host_file_temp_path}/${filename}`);
let cache_file_path = path.join(process.cwd(), host_file_cache_path); // NOTE: This may be needed later? Uncomment if paths are relative to working directory.
// let cache_file_path = path.join(process.cwd(), host_file_cache_path);
let cache_file_path = host_file_cache_path;
console.log(cache_file_path); console.log(cache_file_path);
let hash_filename = hash+'.file'; let hash_filename = hash+'.file';
let full_cache_file_path = path.join(cache_file_path, hash_filename); let full_cache_file_path = path.join(cache_file_path, hash_filename);
console.log(full_cache_file_path); console.log(full_cache_file_path);
open_temp_file_path = path.join(process.cwd(), host_file_temp_path, filename); // 'temp/' // NOTE: This may be needed later? Uncomment if paths are relative to working directory.
// open_temp_file_path = path.join(process.cwd(), host_file_temp_path, filename); // 'temp/'
open_temp_file_path = path.join(host_file_temp_path, filename); // 'temp/'
console.log(open_temp_file_path); console.log(open_temp_file_path);
if (fs.existsSync(open_temp_file_path)) { if (fs.existsSync(open_temp_file_path)) {

2264
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
{ {
"name": "onesky_native", "name": "aether_app_native",
"version": "2.0.0", "productName": "Aether App",
"description": "One Sky Native App", "version": "3.0.0",
"description": "One Sky IT's Native Aether App",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "electron .", "start": "electron .",
@@ -12,12 +13,15 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^0.26.0", "axios": "^0.26.0",
"electron": "^17.1.0",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"os": "^0.1.1", "os": "^0.1.1",
"path": "^0.12.7", "path": "^0.12.7",
"request": "^2.88.2", "request": "^2.88.2",
"screen": "^0.2.10", "screen": "^0.2.10",
"usb": "^1.6.2" "usb": "^1.6.2"
},
"devDependencies": {
"electron": "^17.4.0",
"electron-packager": "^15.4.0"
} }
} }